XMLUtils.js
function XmlUtils(config) {
/* 定義私有屬性 */
this.isIE = !!(window.attachEvent && !window.opera);
this.init();
if (config) {
this.dataType = config.dataType == 'json' ? 'json' : 'array';
if (config.xmlPath)
this.loadXml(config.xmlPath);
}
}
XmlUtils.prototype = {
xmlDoc : null,
xmlPath : null,
dataType : null,
/**
* 初始化
*/
init : function() {
if (this.isIE) {
var activexArr = [ "MSXML4.DOMDocument", "MSXML3.DOMDocument",
"MSXML2.DOMDocument", "MSXML.DOMDocument",
"Microsoft.XmlDom" ];
for ( var i = 0; i < activexArr.length; i++) {
try {
this.xmlDoc = new ActiveXObject(activexArr[i]);
} catch (e) {
}
}
} else {
this.xmlDoc = document.implementation.createDocument("", "", null);
}
},
/**
* 加載xml檔案,參數:
*
* @param {string}
* xmlPath:加載的xml檔案路徑;
* @return {Object} true 正常加載; false 加載失敗
*/
loadXml : function(xmlPath) {
try {
this.xmlDoc.async = false;
this.xmlDoc.load(xmlPath);
this.xmlPath = xmlPath;
return true;
} catch (e) {
return false;
}
},
/**
* 加載XML字元串
*
* @param {Object}
* XMLString
*/
loadXmlString : function(xmlString) {
if (this.isIE) {
this.xmlDoc.loadXML(xmlString);
} else {
var parser = new DOMParser();
this.XMLDoc = parser.parseFromString(xmlString, "text/xml");
}
},
/**
* 判斷節點的是否有子節點
*
* @param {Object}
* node
* @return {Object} 有子節點則傳回true,否則傳回false
*/
hasChildNodes : function(node) {
return node.hasChildNodes();
},
/**
* 判斷節點的是否有屬性
*
* @param {Object}
* node
* @return {Object} 有屬性則傳回true,否則傳回false
*/
hasAttributes : function(node) {
return (node.attributes.length > 0) ? true : false;
},
/**
* 判斷節點的是否是文本節點,包括帶CDATA區段的文本節點
*
* @param {Object}
* node
* @return {Object} 是文本節點則傳回true,否則傳回false
*/
isTextNode : function(node) {
var type = this.getNodeType(node);
return (type == 3 || type == 4) ? true : false;
},
/**
* 傳回根節點
*
* @return {Object} 根節點
*/
getRoot : function() {
return this.xmlDoc.documentElement;
},
/**
* 傳回節點的第一個子節點,沒有參數則傳回根節點的第一個子節點
*
* @param {Object}
* node
* @return {Object} 節點的第一個子節點
*/
getFirstChild : function(node) {
return node ? node.firstChild : this.getRoot().firstChild;
},
/**
* 傳回節點的最後子節點,沒有參數則傳回根節點的第一個子節點
*
* @param {Object}
* node
* @return {Object} 節點的最後一個子節點
*/
getLastChild : function(node) {
return node ? node.lastChild : this.getRoot().lastChild;
},
/**
* 傳回節點的下一個節點,沒有參數則傳回根節點的第一個子節點
*
* @param {Object}
* node
* @return {Object} 節點的下一個節點
*/
getNextNode : function(node) {
return node ? node.nextSibling : null;
},
/**
* 傳回節點的上一個節點,沒有參數則傳回根節點的第一個子節點
*
* @param {Object}
* node
* @return {Object} 節點的上一個節點
*/
getPreviousNode : function(node) {
return node ? node.previousSibling : null;
},
/**
* 傳回節點的子節點,沒有參數則傳回null
*
* @param {Object}
* node
* @return {Object} 節點所有子節點
*/
getChildNodes : function(node) {
return (node && this.hasChildNodes(node)) ? node.childNodes : null;
},
/**
* 傳回節點的父節點,沒有參數則傳回null
*
* @param {Object}
* node
* @return {Object} 節點父節點
*/
getParentNode : function(node) {
return node ? node.parentNode : null;
},
/**
* 根據節點名傳回節點數組文本值,參數:
*
* @param {string或object}
* nodeName:節點名稱;
* @return {object} 節點存在傳回節點數組;節點不存在則傳回null。
*/
getNodesTextByName : function(nodeNames) {
return nodeNames ? (this.dataType == 'json' ? this
.getJsonNodesTextByName(nodeNames) : this
.getArryNodesTextByName(nodeNames)) : null;
},
/**
* 根據節點名傳回節點普通數組文本值,參數:
*
* @param {string或object}
* nodeName:節點名稱;
* @return {object} 節點存在傳回節點普通數組。
*/
getArryNodesTextByName : function(nodeNames) {
var rs = [];
// 傳回普通數組格式
switch (typeof (nodeNames)) {
case 'string':
var nodes = this.getNodesByTagName(nodeNames);
for ( var i = 0; i < nodes.length; i++) {
rs.push(nodes[i].text);
}
break;
case 'object':
var subRs;
var nodes;
for ( var i = 0; i < nodeNames.length; i++) {
nodes = this.getNodesByTagName(nodeNames[i]);
subRs = [];
for ( var j = 0; j < nodes.length; j++) {
subRs.push(nodes[j].text);
}
rs.push(subRs);
}
break;
}
return rs;
},
/**
* 根據節點名傳回節點JSON數組文本值,參數:
*
* @param {string或object}
* nodeName:節點名稱;
* @return {object} 節點存在傳回節點JSON數組;節點不存在則傳回null。
*/
getJsonNodesTextByName : function(nodeNames) {
var rs = null;
// 傳回JSON數組格式
switch (typeof (nodeNames)) {
case 'string':
eval('rs = {' + nodeNames + ':[]}');
var nodes = this.getNodesByTagName(nodeNames);
for ( var i = 0; i < nodes.length; i++) {
eval('rs.' + nodeNames + '.push({' + nodeNames + i
+ ': nodes[i].text})');
}
break;
case 'object':
rs = {};
var nodes;
for ( var i = 0; i < nodeNames.length; i++) {
eval('rs.' + nodeNames[i] + '=[]');
nodes = this.getNodesByTagName(nodeNames[i]);
for ( var j = 0; j < nodes.length; j++) {
eval('rs.' + nodeNames[i] + '.push({' + nodeNames[i] + j
+ ': nodes[j].text})');
}
}
break;
}
return rs;
},
/**
* 根據節點屬性得到節點,參數:
*
* @param {String}
* key:屬性名,預設是id
* @param {String}
* value:屬性值
* @return {String} 符合條件的節點數組。
*/
getNodesByAttribute : function(key, value) {
key = key ? key : 'id';
value = value ? value : '';
return id ? this.xmlDoc.getElementById(id) : null;
},
/**
* 根據節點名得到節點,參數:
*
* @param {string}
* tagName:節點名稱
* @return {string} 指定節點名字的和位置的節點或節點數組。
*/
getNodesByTagName : function(tagName) {
return tagName ? this.xmlDoc.getElementsByTagName(tagName) : null;
},
/**
* 根據節點路徑傳回第index個節點,參數:
*
* @param {string}
* xPath:節點路徑
* @param {number}index:要索引的位置,為空或0則傳回所有查找到的節點。
* @return {string} 指定節點名字的和位置的節點或節點數組。
*/
getNodesByXpath : function(xPath, index) {
if (!xPath)
return null;
var nodes = this.xmlDoc.selectNodes(xPath);
var len = nodes.length;
if (!index || index > len || index < 0)
return nodes;
for ( var i = 0; i < len; i++) {
if (i == index - 1)
return nodes[i];
}
},
/**
* 得到指定節點文本,參數:
*
* @param {object}
* node:節點
* @return {string} 節點文本,為空則傳回null
*/
getText : function(node) {
return node ? node.text : null;
},
/**
* 得到指定節點名稱,參數:
*
* @param {object}
* node:節點
* @return {string} 節點名稱,為空則傳回null
*/
getTagName : function(node) {
return node ? node.nodeName : null;
},
/**
* 傳回節點類型,參數:
*
* @param {object}
* node:節點
* @return {string} 節點類型,為空則傳回null 1-element 2-attribute 3-text 4-cdata
* 5-entity reference 6-entity 7-pi (processing instruction)
* 8-comment 9-document 10-document type 11-document fragment
* 12-notation
*/
getNodeType : function(node) {
return node ? node.nodeType : null;
},
/**
* 建立節點,參數:
*
* @param {string}
* nodeName:節點名稱,必填
* @param {string}
* text:節點文本,可為空
* @param {Object}
* attributes:屬性值-JSON數組,可為空,例:{id:'id001',name:'name001'}
* @param {Object}
* node:要增加子節點的節點,為空則傳回建立的節點
* @param {Boolean}
* cdata:是否生成帶有CDATA區段的節點,true:生成,false:不生成
* @return {Object} 建立的節點,有異常則傳回null
*/
createNode : function(nodeName, text, attributes, node, cdata) {
if (this.isIE) {
// 建立子接點
var childNode = this.xmlDoc.createElement(nodeName);
// 建立文本節點
var textNode = cdata == true ? this.xmlDoc.createCDATASection(text)
: this.xmlDoc.createTextNode(text);
childNode.appendChild(textNode);
// 添加屬性
for ( var i in attributes) {
this.createAttribute(childNode, i, attributes[i]);
}
;
return node ? node.appendChild(childNode) : childNode;
} else {
alert('火狐浏覽器建立節點再說.');
return null;
}
},
/**
* 建立帶CDATA區段的節點,參數:
*
* @param {string}
* nodeName:節點名稱,必填
* @param {string}
* text:節點文本,可為空
* @param {Object}
* attributes:屬性值-JSON數組,可為空,例:{id:'id001',name:'name001'}
* @param {Object}
* node:要增加子節點的節點,為空則傳回建立的節點
*/
createCDATANode : function(nodeName, text, attributes, node) {
this.createNode(nodeName, text, attributes, node, true);
},
/**
* 建立節點屬性,參數:
*
* @param {Object}
* node:節點,必填
* @param {String}
* key:屬性名,必填
* @param {Object}
* value:屬性值,必填
* @param {Object}
* node:傳回新增屬性的節點
* @return {Object} 增加屬性的節點,有異常則傳回null
*/
createAttribute : function(node, key, value) {
if (this.isIE) {
if (!key)
return;
var attr = this.xmlDoc.createAttribute(key);
attr.value = value ? value : "";
node.setAttributeNode(attr);
return node;
} else {
alert('火狐浏覽器建立節點再說.');
return node;
}
return null;
},
/**
* 把節點加到根節點上,參數:
*
* @param {Object}
* node:節點
* @return {Object} 有異常則傳回null
*/
addNodeToRoot : function(node) {
if (!node)
return null;
this.getRoot().appendChild(node);
return node;
},
/**
* 把節點加到另外節點上,參數:
*
* @param {Object}
* node:節點
*/
addNode : function(node, childNode) {
return (node && childNode) ? node.appendChild(childNode) : false;
},
/**
* 把節點加到另外節點上,參數:
*
* @param {Object}
* node:節點
*/
addNode : function(node, childNode) {
return (node && childNode) ? node.appendChild(childNode) : false;
},
/**
* 從父節點移除節點自身,參數:
*
* @param {Object}
* node:要移除的節點
*/
removeChild : function(node) {
if (!node || !node.parentNode)
return;
node.parentNode.removeChild(node);
},
/**
* 移除節點的所有子節點,參數:
*
* @param {Object}
* node:父節點
*/
removeChildNodes : function(node) {
if (node && this.hasChildNodes(node)) {
var childNodes = node.childNodes;
for ( var i = 0; i < childNodes.length; i++) {
node.removeChild(childNodes[0]);
}
}
},
/**
* 設定節點屬性值,不存在則建立,參數:
*
* @param {Object}
* node:要設定的節點
* @param {String}
* key:要設定的屬性名
* @param {String}
* value:要設定的屬性值
*/
setAttribute : function(node, key, value) {
this.createAttribute(node, key, value);
},
/**
* 設定文本節點的文本,參數:
*
* @param {Object}
* node:要設定的節點
* @param {String}
* text:要設定的文本
*/
setText : function(node, text) {
if (this.isTextNode(node))
node.text = text;
},
/**
* 在文本節點後面追加文本,參數:
*
* @param {Object}
* node:要設定的節點
* @param {String}
* text:要設定的文本
*/
appendText : function(node, text) {
if (this.isTextNode(node))
node.appendData(text);
},
/**
* 輸出xml,為空則輸出根節點文本,參數:
*
* @param {Object}
* node:要輸出的節點
*/
toString : function(node) {
node = node ? node : this.xmlDoc.documentElement;
if (typeof node == 'string') {
return node;
}
return this.isIE ? node.xml : new XMLSerializer().serializeToString(node);
}
};
測試 xml資料:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<book>
<name>西遊記</name>
<author>吳承恩</author>
</book>
<book>
<name>紅樓夢</name>
<author>曹雪芹</author>
</book>
<book>
<name>三國演義</name>
<author>羅貫中</author>
</book>
<book>
<name>水浒傳</name>
<author>施耐庵</author>
</book>
</root>
測試jsp頁面:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>js解析XML檔案</title>
</head>
<body>
<div id="xmlOpTest">
</div>
</body>
<script type="text/javascript" src="/js/XmlUtils.js"></script>
<script type="text/javascript">
//config參數:xmlPath檔案位址;dataType資料格式-json或arry,預設為array。
var xmlUtils = new XmlUtils({
xmlPath:"/xmlData/book.xml",
dataType:"xml"
});
//擷取XML内容
alert(xmlUtils.toString());
var rs = xmlUtils.getNodesTextByName(['name','author']);
//把上面的dataType改為array或者不為json此處就能得到值
document.getElementById("xmlOpTest").innerHTML += '<br/>取得所有的文本節點的數組: '+rs + '<br/>';
var root = xmlUtils.getRoot();
//alert(root);
xmlUtils.createNode('publish', '中國電力出版社',{id:'id0001'},root);
xmlUtils.createCDATANode('publish', '中國&電力出版社',{},root);
//設定屬性
xmlUtils.setAttribute(root,'testId','test');
//修改屬性
xmlUtils.setAttribute(root,'testId','test0000000000');
alert(xmlUtils.toString(root));
//删除第一個節點 publish
xmlUtils.removeChild(xmlUtils.getNodesByXpath('//root/publish')[0]);
alert(xmlUtils.toString(root));
var node = xmlUtils.getFirstChild();
//+ xmlUtils.hasAttributes(node) +'<br/>';
document.getElementById("xmlOpTest").innerHTML += '<br/>判斷是否有子節點: '+ xmlUtils.hasChildNodes(node) + ' ------ 判斷是否有屬性:';
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的第一個節點: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +' ======== 節點類型:' + xmlUtils.getNodeType(node) + '<br/>';
node = xmlUtils.getNextNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的第一個節點下一個節點: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getLastChild();
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的最後一個節點: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getPreviousNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的最後一個前一個節點: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node) +'<br/>';
node = xmlUtils.getParentNode(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的父節點: '+ xmlUtils.toString(node) +'<br/>';
var nodes = xmlUtils.getChildNodes();
document.getElementById('xmlOpTest').innerHTML += '<br/>得到節點的所有子節點: '+xmlUtils.toString(nodes)+'<br/>';
node = xmlUtils.getNodesByXpath('//root/book/name',2);
document.getElementById('xmlOpTest').innerHTML += '<br/>根據xPath得到節點名稱和文本值: '+xmlUtils.getTagName(node) + "---" + xmlUtils.getText(node)+'<br/>';
node = xmlUtils.getNodesByXpath('//root/book/author');
document.getElementById('xmlOpTest').innerHTML += '<br/>根據xPath得到節點名稱和文本值: '+xmlUtils.getTagName(node[0]) + "---" + xmlUtils.getText(node[0])+'<br/>';
//得到修改後的文本節點
node = xmlUtils.getNodesByXpath('//root/publish',1);
node = xmlUtils.getFirstChild(node);
document.getElementById('xmlOpTest').innerHTML += '<br/>修改文本值前節點文本: '+xmlUtils.getText(node);
xmlUtils.setText(node,"西遊記後傳");
document.getElementById('xmlOpTest').innerHTML += '-----修改文本值後節點文本: '+xmlUtils.getText(node);
xmlUtils.appendText(node,"之測試");
document.getElementById('xmlOpTest').innerHTML += '-----追加文本值後節點文本: '+xmlUtils.getText(node) + "<br/>";
</script>
</html>