Search This Blog

a complete javascript XML library

xml = {
 // ELEMENT_NODE : 1,
 // ATTRIBUTE_NODE : 2,
 // TEXT_NODE : 3,
 // CDATA_SECTION_NODE : 4,
 // PROCESSING_INSTRUCTION_NODE : 7,
 // COMMENT_NODE : 8,
 // DOCUMENT_NODE : 9,
 // DOCUMENT_TYPE_NODE : 10,
 // DOCUMENT_FRAGMENT_NODE : 11,
 /**
  * Parse the specified XML text into a XML document object.
  * 
  * @param {String}
  *            xmlText
  * @return {XMLDocument}
  */
 parse : function(xmlText) {
  if (typeof DOMParser !== 'undefined') {
   // W3C(Mozilla Firefox, Safari) or IE 9 (standard mode)
   return (new DOMParser()).parseFromString(xmlText, 'text/xml');
  } else if (typeof ActiveXObject !== 'undefined') {
   // IE6 ~ IE8
   var doc = new ActiveXObject('Microsoft.XMLDOM');
   doc.async = 'false';
   doc.loadXML(xmlText);
   return doc;
  } else {
   // Safari
   var url = 'data:text/xml;charset=utf-8,'
     + encodeURIComponent(xmlText);
   var request = new XMLHttpRequest();
   request.open('GET', url, false);
   request.send(null);
   doc = request.responseXML;
   return doc;
  }
 },
 /**
  * Serialize the XML Object into string/text.
  * 
  * @param {XMLNode}
  *            xmlObject
  * @return {String}
  */
 serialize : function(xmlObject) {
  if (xmlObject.xml) {
   // IE6 ~ IE8
   return xmlObject.xml;
  } else {
   // W3C(Mozilla Firefox, Safari) or IE 9 (standard mode)
   return (new XMLSerializer()).serializeToString(xmlObject);
  }
 },
 /**
  * Create a XML document object.
  * 
  * @param {String}
  *            rootTagName
  * @param {String}
  *            namespaceURL
  * @return {XMLDocument}
  */
 create : function(rootTagName, namespaceURL) {
  rootTagName = rootTagName || '';
  namespaceURL = namespaceURL || '';
  if (document.implementation && document.implementation.createDocument) {
   // W3C
   return document.implementation.createDocument(namespaceURL,
     rootTagName, null);
  } else {
   // IE6 ~ IE8
   var doc = new ActiveXObject('MSXML2.DOMDocument');
   if (rootTagName) {
    var prefix = '';
    var tagName = rootTagName;
    var p = rootTagName.indexOf(':');
    if (p != -1) {
     prefix = rootTagName.substring(0, p);
     tagName = rootTagName.substring(p + 1);
    }
    if (namespaceURL) {
     if (!prefix) {
      prefix = 'a0'; // What Firefox uses
     }
    } else {
     prefix = '';
    }
    var text = '<'
      + (prefix ? (prefix + ':') : '')
      + tagName
      + (namespaceURL ? (' xmlns:' + prefix + '="'
        + namespaceURL + '"') : '') + '/>';
    doc.loadXML(text);
   }
   return doc;
  }
 },
 /**
  * Load XML document from the sepcified url synchronously.
  * 
  * @param {String}
  *            url
  * @return {XMLDocument}
  */
 loadSync : function(url) {
  var doc = (document.implementation && document.implementation.createDocument)
    ? document.implementation.createDocument(null, null, null)
    : new ActiveXObject('MSXML2.DOMDocument');
  if (doc) {
   doc.async = false;
   try {
    doc.load(url);
   } catch (e) {
    doc = null;
   }
   if (doc) {
    return doc;
   }
  } else {
   // Method 2: use XMLHttpRequest
   if (window.XMLHttpRequest && !window.ActiveXObject) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, false);
    xhr.send(null);
    return xhr.responseXML;
   } else {
    doc = new ActiveXObject('Microsoft.XMLDOM');
    doc.async = false;
    doc.load(url);
    return doc;
   }
  }
 },
 /**
  * Load xml document from the sepcified url asynchronously.
  * 
  * @param {String}
  *            url
  * @param {Function}
  *            callback
  */
 loadAsync : function(url, callback) {
  var doc = (document.implementation && document.implementation.createDocument)
    ? document.implementation.createDocument(null, null, null)
    : new ActiveXObject('MSXML2.DOMDocument');
  if (doc) {
   doc.async = true;
   if (document.implementation
     && document.implementation.createDocument) {
    // W3C
    doc.onload = function() {
     callback(doc);
    };
   } else {
    // IE
    doc.onreadystatechange = function() {
     if (doc.readyState == 4) {
      callback(doc);
     } else {
      throw new Error('Failed loading XML doc. readyState='
        + doc.readyState);
     }
    };
   }
   doc.load(url);
  } else {
   // Method 2: use XMLHttpRequest
   if (window.XMLHttpRequest && !window.ActiveXObject) {
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
     if (xhr.readyState == 4 && xhr.status == 200) {
      callback(xhr.responseXML);
     } else {
      throw new Error('XMLHttpRequest failed with readystate: '
        + xhr.readyState);
     }
    }
   } else {
    doc = new ActiveXObject('Microsoft.XMLDOM');
    if (callback) {
     doc.async = true;
     doc.onreadystatechange = function() {
      if (doc.readyState == 4) {
       callback(doc);
      } else {
       throw new Error('Failed loading XML doc. readyState='
         + doc.readyState);
      }
     }
     doc.load(url);
    }
   }
  }
 },
 /**
  * Select single node from the specified XML object(node) by evaluate the
  * specified xpath expression.
  * 
  * @param {XMLNode}
  *            xmlObject
  * @param {String}
  *            xpath
  * @return {XMLNode}
  */
 selectSingleNode : function(xmlObject, xpath) {
  var node = null;
  if (window.ActiveXObject
    && typeof xmlObject.selectSingleNode !== 'undefined') {
   // IE: MSXML object
   node = xmlObject.selectSingleNode(xpath);
  } else if (window.XPathEvaluator
    && document.implementation.hasFeature('XPath', '3.0')) {
   // W3C Browsers
   // FIRST_ORDERED_NODE_TYPE returns the first match to the xpath.
   var result = (new XPathEvaluator()).evaluate(xpath, xmlObject,
     null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
   if (typeof result != 'undefined' && result != null) {
    node = result.singleNodeValue;
   }
  }
  return node;
 },
 /**
  * Select single value from the specified XML object(node) by evaluate the
  * specified xpath expression.
  * 
  * @param {XMLNode}
  *            xmlObject
  * @param {String}
  *            xpath
  * @return {String}
  */
 selectSingleValue : function(xmlObject, xpath) {
  var value;
  var node = xml.selectSingleNode(xmlObject, xpath);
  if (node) {
   if (node.nodeType === 2) {
    // ATTRIBUTE_NODE : 2
    value = node.nodeValue;
   } else if (node.nodeType === 1) {
    // ELEMENT_NODE : 1
    node.normalize();
    for (var j = 0; j < node.childNodes.length; j++) {
     var childNode = node.childNodes[j];
     if (childNode.nodeType === 3) {
      // TEXT_NODE : 3
      value = childNode.nodeValue;
      break;
     }
    }
   }
  }
  return value;
 },
 /**
  * Select a set of XML nodes from the specified xmlObject by evaluate the
  * specified xpath expression.
  * 
  * @param {XMLNode}
  *            xmlObject
  * @param {String}
  *            xpath
  * @return {[XMLNode]}
  */
 selectNodes : function(xmlObject, xpath) {
  var nodes = [];
  if (window.ActiveXObject
    && typeof xmlObject.selectNodes !== 'undefined') {
   nodes = xmlObject.selectNodes(xpath);
  } else if (window.XPathEvaluator
    && document.implementation.hasFeature('XPath', '3.0')) {
   var nsResolver = function(prefix) {
    return prefix;
   }
   var result = (new XPathEvaluator()).evaluate(xpath, xmlObject,
     nsResolver, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
   var nodes = [];
   if (typeof result != 'undefined' && result != null) {
    var node;
    while (node = result.iterateNext()) {
     nodes.push(node);
    }
   }
  }
  return nodes;
 },
 /**
  * Select a set of XML node values from the specified xmlObject by evaluate
  * the specified xpath expression.
  * 
  * @param {XMLNode}
  *            xmlObject
  * @param {String}
  *            xpath
  * @return {[String]} value set
  */
 selectValues : function(xmlObject, xpath) {
  var values = [];
  var nodes = xml.selectNodes(xmlObject, xpath);
  if (typeof nodes !== 'undefined' && nodes != null) {
   for (var i = 0; i < nodes.length; i++) {
    var node = nodes[i];
    switch (node.nodeType) {
     case 2 :
      // ATTRIBUTE_NODE : 2
      values.push(node.nodeValue);
      break;
     case 1 :
      // ELEMENT_NODE : 1
      node.normalize();
      var text;
      for (var j = 0; j < node.childNodes.length; j++) {
       var childNode = node.childNodes[j];
       if (childNode.nodeType === 3) {
        // TEXT_NODE : 3
        text = childNode.nodeValue;
        break;
       }
      }
      if (typeof text !== 'undefined' && text != null) {
       values.push(text);
      }
      break;
    }
   }
  }
  return values;
 }
};

selectSingleNode and selectNodes in IE

Documentation about selectNodes
Documentation about selectSingleNode