XmlUtils JS操作XML工具类


Posted in Javascript onOctober 01, 2009

demo用了点extjs的东西,主要是为了打印json数组出来。
js code(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(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('FF创建节点再说.'); 
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('FF创建节点再说.'); 
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} newNode:要替换的节点 
* @param {Object} oldNode:要被替换的节点 
*/ 
replaceChild: function(newNode, oldNode) { 
var parentNode = oldNode.parentNode; 
if(!newNode || !oldNode || !parentNode) return; 
parentNode.replaceChild(newNode, oldNode); 
}, 
/** 
* 从父节点移除节点自身,参数: 
* @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文件(book.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> 
<name>施耐庵</name> 
<sex>男</sex> 
</author> 
</book> 
<book> 
<name>水浒传</name> 
<author>罗贯中</author> 
</book> 
</root>

html code (test.html):
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
<script language="JavaScript" type="text/javascript" src="../Ext/ext-base.js" ><!-- // --></script> 
<script language="JavaScript" type="text/javascript" src="../Ext/ext-all.js" ><!-- 
// --></script> 
<title>测试xml</title> 
<script src="XmlUtils.js"></script> 
</head> 
<body> 
<div id='xmlOpTest'></div> 
</body> 
<script type="text/javascript"><!-- 
/** 
* config参数:xmlPath文件地址;dataType数据格式-json或arry,默认为array。 
*/ 
var xmlUtils = new XmlUtils({xmlPath:"book.xml",dataType:'json'}); 
alert(xmlUtils.toString()); 
var rs = xmlUtils.getNodesTextByName(['name','author']); 
//把上面的dataType改为array或者不为json此处就能得到值 
document.getElementById('xmlOpTest').innerHTML += '<br/>取得所有的文本节点的数组: '+rs + '<br/>'; 
//这里用了Ext的json解析工具 Ext.encode这个方法是把json对象转换为字符串。Ext.decode则相反,把json格式的字符串转换为json对象数组 
document.getElementById('xmlOpTest').innerHTML += '<br/>取得所有的文本节点的JSON数组: '+Ext.encode(rs)+'<br/>'; 
var root = xmlUtils.getRoot(); 
xmlUtils.createNode('publish', '中国电力出版社',{id:'id0001'},root); 
xmlUtils.createCDATANode('publish', '中国&电力出版社',{},root); 
//设置属性 
xmlUtils.setAttribute(root,'testId','test'); 
//修改属性 
xmlUtils.setAttribute(root,'testId','test0000000000'); 
alert(xmlUtils.toString(root)); 
xmlUtils.removeChild(xmlUtils.getNodesByXpath('//root/publish')[0]); 
alert(xmlUtils.toString(root)); 
node = xmlUtils.getFirstChild(); 
document.getElementById('xmlOpTest').innerHTML += '<br/>判断是否有子节点: '+xmlUtils.hasChildNodes(node) + ' ------ 判断是否有属性:';//+ xmlUtils.hasAttributes(node) +'<br/>'; 
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>

上面的文件都上传了,正在审核中,等审核通过了我会发到这里的。
Javascript 相关文章推荐
JavaScript设计模式之单例模式实例
Sep 24 Javascript
jQuery中:password选择器用法实例
Jan 03 Javascript
JS实现的简单鼠标跟随DiV层效果完整实例
Oct 31 Javascript
微信小程序 HTTPS报错整理常见问题及解决方案
Dec 14 Javascript
深入理解vue Render函数
Jul 19 Javascript
Node.js服务器开启Gzip压缩教程
Aug 11 Javascript
ES6中Array.copyWithin()函数的用法实例详解
Sep 16 Javascript
微信小程序button组件使用详解
Jan 31 Javascript
Vue多种方法实现表头和首列固定的示例代码
Feb 02 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
May 26 jQuery
基于vue+uniapp直播项目实现uni-app仿抖音/陌陌直播室功能
Nov 12 Javascript
Ant Design moment对象和字符串之间的相互转化教程
Oct 27 Javascript
PPK 谈 JavaScript 的 this 关键字 [翻译]
Sep 29 #Javascript
一个JS小玩意 几个属性相加不能超过一个特定值.
Sep 29 #Javascript
IE FF OPERA都可用的弹出层实现代码
Sep 29 #Javascript
javascript 表单验证常见正则
Sep 28 #Javascript
javascript 页面划词搜索JS
Sep 28 #Javascript
jquery 模式对话框终极版实现代码
Sep 28 #Javascript
javascript的onchange事件与jQuery的change()方法比较
Sep 28 #Javascript
You might like
编译php 5.2.14+fpm+memcached(具体操作详解)
2013/06/18 PHP
PHP读MYSQL中文乱码的快速解决方法
2016/10/01 PHP
Django 标签筛选的实现代码(一对多、多对多)
2018/09/05 PHP
用tip解决Ext列宽度不够的问题
2008/12/13 Javascript
Javascript中 关于prototype属性实现继承的原理图
2013/04/16 Javascript
jQuery随机切换图片的小例子
2013/04/18 Javascript
window.opener用法和用途实例介绍
2013/08/19 Javascript
JavaScript获取路径设计源码
2014/05/22 Javascript
jquery实现保存已选用户
2014/07/21 Javascript
JavaScript之Object类型介绍
2015/04/01 Javascript
JavaScript如何实现对数字保留两位小数一位自动补零
2015/12/18 Javascript
浅谈Sticky组件的改进实现
2016/03/22 Javascript
巧方法 JavaScript获取超链接的绝对URL地址
2016/06/14 Javascript
JS中this上下文对象使用方式
2016/10/09 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
Jquery获取radio选中的值
2017/05/05 jQuery
Angular2中select用法之设置默认值与事件详解
2017/05/07 Javascript
详解在vue-cli项目中安装node-sass
2017/06/21 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
浅谈webpack-dev-server的配置和使用
2018/05/17 Javascript
[01:01:18]VP vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
对tensorflow 的模型保存和调用实例讲解
2018/07/28 Python
对python 树状嵌套结构的实现思路详解
2019/08/09 Python
python3 selenium自动化 frame表单嵌套的切换方法
2019/08/23 Python
利用python、tensorflow、opencv、pyqt5实现人脸实时签到系统
2019/09/25 Python
Python Tricks 使用 pywinrm 远程控制 Windows 主机的方法
2020/07/21 Python
Python面向对象特殊属性及方法解析
2020/09/16 Python
伦敦一卡通:The London Pass
2018/11/30 全球购物
如何开启linux的ssh服务
2015/02/14 面试题
爷爷追悼会答谢词
2014/01/24 职场文书
幼儿园中班教学反思
2014/02/10 职场文书
岗位工作说明书
2014/07/29 职场文书
师范生小学见习总结
2015/06/23 职场文书
幼儿园安全管理制度
2015/08/05 职场文书
Flask搭建一个API服务器的步骤
2021/05/28 Python
gateway网关接口请求的校验方式
2021/07/15 Java/Android