// author: yangyi ([email protected])
// Based on <http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247> (copy from ajaxslt)
var DOM_ELEMENT_NODE = 1;
var DOM_ATTRIBUTE_NODE = 2;
var DOM_TEXT_NODE = 3;
var DOM_CDATA_SECTION_NODE = 4;
var DOM_ENTITY_REFERENCE_NODE = 5;
var DOM_ENTITY_NODE = 6;
var DOM_PROCESSING_INSTRUCTION_NODE = 7;
var DOM_COMMENT_NODE = 8;
var DOM_DOCUMENT_NODE = 9;
var DOM_DOCUMENT_TYPE_NODE = 10;
var DOM_DOCUMENT_FRAGMENT_NODE = 11;
var DOM_NOTATION_NODE = 12;
/**
* http://developer.mozilla.org/en/docs/DOMParser
* 接受一段xml,解析成为xml document对象
* 调用时可用try{}catch(e){}捕捉错误,错误对象具有parser xml message属性
* @param {String} xml string
* @return {Object} xml document object
*/
function xmlDocument(/* String */xmlString){
var doc = null;
if (window.ActiveXObject){
var ActiveIds = ['MSXML2.XMLDOM', 'Microsoft.XMLDOM', 'MSXML.XMLDOM', 'MSXML3.XMLDOM'];
for (var len = ActiveIds.length, i = 0; i < len; i++){
var id = ActiveIds[i];
try{
var doc = new ActiveXObject(id);
doc.async = false;
doc.setProperty('SelectionLanguage', 'XPath');
doc.loadXML(xmlString);
break;
}catch (e){}finally{
if (doc && doc.parseError && doc.parseError.errorCode != 0){
throw {parser:'MSXML', message:doc.parseError.reason, xml:xmlString, func:'xmlDocument'};
}
}
}
}else if (typeof DOMParser != 'undefined'){
var parser = new DOMParser();
var doc = parser.parseFromString(xmlString, 'text/xml');
if (doc.documentElement.nodeName == 'parsererror'){
throw {parser:'DOMParser', message:doc.documentElement.firstChild.nodeValue, xml:xmlString, func:'xmlDocument'};
}
}else{ return false; }
return doc;
}
/**
* 获取指定节点或文档对象的xml内容
* port from ajaxslt xmlText()
* @param {Object} xml DOM Node or xml Document
* @return {String} xml string
*/
function xmlText(/* Document|Element */node){
if (typeof node == 'string'){ return node; }
if (node.innerXML){
return node.innerXML;
}else if (node.xml){
return node.xml;
}else if (typeof XMLSerializer != 'undefined'){
return (new XMLSerializer()).serializeToString(node);
}else{ return false; }
}
/**
* 获取所有节点的内容
* port from ajaxslt xmlValue()
* @param {Object} xml DOM Node or xml Document
* @return {String}
*/
function xmlValue(/* Document|Element */node){
var val = '';
if (node.nodeType == DOM_TEXT_NODE ||
node.nodeType == DOM_CDATA_SECTION_NODE ||
node.nodeType == DOM_ATTRIBUTE_NODE){
val += node.nodeValue;
}else if (node.nodeType == DOM_ELEMENT_NODE ||
node.nodeType == DOM_DOCUMENT_NODE ||
node.nodeType == DOM_DOCUMENT_FRAGMENT_NODE){
for (var len = node.childNodes.length, i = 0; i < len; i++){
val += arguments.callee(node.childNodes[i]);
}
}
return val;
}
/**
* 获取节点属性,以对象形式返回
* @param {Object}
* @return {Object}
*/
function xmlGetAttributes(/* Element */node){
var result = {};
var nodeMap = node.attributes;
if (nodeMap){
for (var len = nodeMap.length, i = 0; i < len; i++){
var aNode = nodeMap.item(i);
result[aNode.nodeName] = aNode.nodeValue;
}
}
return result;
}
/**
* 设置节点属性
* @param {Object} xml DOM Node
* @param {Object} attribute data as object type
* @return {Void}
*/
function xmlSetAttributes(/* Element */node, /* Object */attributes){
var attributes = attributes || {};
for (key in attributes){
node.setAttribute(key, attributes[key]);
}
}
/**
* 使用xpath在xml树中查询
* http://developer.mozilla.org/en/docs/Introduction_to_using_XPath_in_JavaScript
* @param {Object} xml Document or xml DOM Node
* @param {String} xpath query string
* @param {Boolean} if set true, only return first result node
* @return {Mixed} return array include all nodes or first node
*/
function xpathSelectNodes(/* Document|Element */root, /* String */query, /* Boolean */returnFirst){
if (window.ActiveXObject){
return returnFirst ? root.selectSingleNode(query) : root.selectNodes(query);
}else if (document.evaluate){
/**
* DOMParser的return type有ordered和unordered两种
* ordered会按照树中间的顺序排列结果,unordered不一定
* 另外还有一种snapshots的,这种结果是树节点的一个clone
* 也就是说,如果操作结果节点,原来的节点不会有改变
* 这里使用非clone方式
*/
var returnType = returnFirst ? XPathResult.FIRST_ORDERED_NODE_TYPE : XPathResult.ORDERED_NODE_ITERATOR_TYPE;
var doc = (root.nodeType == DOM_DOCUMENT_NODE) ? root : root.ownerDocument;
var root = (root.nodeType == DOM_DOCUMENT_NODE) ? root.documentElement : root;
var result = doc.evaluate(query, root, null, returnType, null);
if (returnFirst){
var nodes = result.singleNodeValue;
}else{
var nextNode = result.iterateNext();
var nodes = [];
while (nextNode){
nodes.push(nextNode);
nextNode = result.iterateNext();
}
}
}
return nodes;
}
/**
* http://developer.mozilla.org/en/docs/Transforming_XML_with_XSLT
* http://developer.mozilla.org/en/docs/Using_the_Mozilla_JavaScript_interface_to_XSL_Transformations
* @param {Mixed} source xml, xml string or xml Document or xml DOM Node
* @param {Mixed} xslt style sheet, xml string or xml Document or xml DOM Node
* @param {Boolean} if set true, return processed xml as Document
* @return {Mixed} return string or Document
*/
function xsltProcess(/* String|Document|Element */srcDoc, /* String|Document|Element */stylesheet, /* Boolean */returnAsDoc){
var returnAsDoc = (typeof returnAsDoc == 'undefined') ? false : returnAsDoc;
try{
var srcDoc = (typeof srcDoc == 'string') ? xmlDocument(srcDoc) : srcDoc;
var stylesheet = (typeof stylesheet == 'string') ? xmlDocument(stylesheet) : stylesheet;
}catch(e){ e.func = 'xsltProcess'; throw e; }
if (typeof XSLTProcessor != 'undefined'){
var processor = new XSLTProcessor();
try{
processor.importStylesheet(stylesheet);
var dest = processor.transformToDocument(srcDoc);
return returnAsDoc ? dest : xmlText(dest);
}catch(e){ throw {func:'xsltProcess', processor:'XSLTProcessor', xml:xmlText(srcDoc), xslt:xmlText(stylesheet)}; }
}else if (window.ActiveXObject){
try{
var dest = srcDoc.transformNode(stylesheet);
return returnAsDoc ? xmlDocument(dest) : dest;
}catch(e){ throw {func:'xsltProcess', processor:'MSXML', xml:xmlText(srcDoc), xslt:xmlText(stylesheet)}; }
}
return false;
}
|