| /* | 
|  * @copyright | 
|  * Copyright © Microsoft Open Technologies, Inc. | 
|  * | 
|  * All Rights Reserved | 
|  * | 
|  * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  * you may not use this file except in compliance with the License. | 
|  * You may obtain a copy of the License at | 
|  * | 
|  * http: *www.apache.org/licenses/LICENSE-2.0 | 
|  * | 
|  * THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS | 
|  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION | 
|  * ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A | 
|  * PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT. | 
|  * | 
|  * See the Apache License, Version 2.0 for the specific language | 
|  * governing permissions and limitations under the License. | 
|  */ | 
| 'use strict'; | 
|   | 
| var _ = require('underscore'); | 
| var select = require('xpath.js'); | 
| var XMLSerializer = require('xmldom').XMLSerializer; | 
|   | 
| var constants = require('./constants'); | 
|   | 
| /** | 
|  * @namespace XmlUtil | 
|  * @private | 
|  */ | 
|   | 
| var XPATH_PATH_TEMPLATE = '*[local-name() = \'LOCAL_NAME\' and namespace-uri() = \'NAMESPACE\']'; | 
| /** | 
| * The xpath implementation being used does not have a way of matching expanded namespace. | 
| * This method takes an xpath query and expands all of the namespaces involved.  It then | 
| * re-writes the query in to a longer form that directory matches the correct namespaces. | 
| * @private | 
| * @static | 
| * @memberOf XmlUtil | 
| * @param {string} xpath   The expath query string to expand. | 
| * @returns {string} An expanded xpath query. | 
| */ | 
| function expandQNames(xpath) { | 
|   var namespaces = constants.XmlNamespaces; | 
|   var pathParts = xpath.split('/'); | 
|   for (var i=0; i < pathParts.length; i++) { | 
|     if (pathParts[i].indexOf(':') !== -1) { | 
|       var QNameParts = pathParts[i].split(':'); | 
|       if (QNameParts.length !== 2) { | 
|         throw new Error('Unable to parse XPath string : ' + xpath + ' : with QName : ' + pathParts[i]); | 
|       } | 
|       var expandedPath = XPATH_PATH_TEMPLATE.replace('LOCAL_NAME', QNameParts[1]); | 
|       expandedPath = expandedPath.replace('NAMESPACE', namespaces[QNameParts[0]]); | 
|       pathParts[i] = expandedPath; | 
|     } | 
|   } | 
|   return pathParts.join('/'); | 
| } | 
|   | 
| var exports = { | 
|   | 
|   /** | 
|    * Performs an xpath select that does appropriate namespace matching since the imported | 
|    * xpath module does not properly handle namespaces. | 
|    * @static | 
|    * @memberOf XmlUtil | 
|    * @param  {object} dom     A dom object created by the xmldom module | 
|    * @param  {string} xpath   An xpath expression | 
|    * @return {array}          An array of matching dom nodes. | 
|    */ | 
|   xpathSelect :  function (dom, xpath) { | 
|     return select(dom, expandQNames(xpath)); | 
|   }, | 
|   | 
|   /** | 
|    * Given a dom node serializes all immediate children that are xml elements. | 
|    * @static | 
|    * @memberOf XmlUtil | 
|    * @param  {object} node  An xml dom node. | 
|    * @return {string}       Serialized xml. | 
|    */ | 
|   serializeNodeChildren : function(node) { | 
|     var doc = ''; | 
|     var sibling = node.firstChild; | 
|     var serializer = new XMLSerializer(); | 
|   | 
|     while (sibling) { | 
|       if (this.isElementNode(sibling)) { | 
|         doc += serializer.serializeToString(sibling); | 
|       } | 
|       sibling = sibling.nextSibling; | 
|     } | 
|   | 
|     return doc !== '' ? doc : null; | 
|   }, | 
|   | 
|   /** | 
|    * Detects whether the passed in dom node represents an xml element. | 
|    * @static | 
|    * @memberOf XmlUtil | 
|    * @param  {object}  node   An xml dom node. | 
|    * @return {Boolean}        true if the node represents an element. | 
|    */ | 
|   isElementNode : function(node) { | 
|     return _.has(node, 'tagName'); | 
|   }, | 
|   | 
|   /** | 
|    * Given an xmldom node this function returns any text data contained within. | 
|    * @static | 
|    * @memberOf XmlUtil | 
|    * @param  {object} node  An xmldom node from which the data should be extracted. | 
|    * @return {string}       Any data found within the element or null if none is found. | 
|    */ | 
|   findElementText : function(node) { | 
|     var sibling = node.firstChild; | 
|     while (sibling && !sibling.data) { | 
|       sibling = sibling.nextSibling; | 
|     } | 
|   | 
|     return sibling.data ? sibling.data : null; | 
|   } | 
| }; | 
|   | 
| module.exports = exports; |