JavaScript对于XML的读取,一般有两种方式:1.利用DOM进行读取。2.利用XPath进行。XPath是一门在XML中查找信息的语言,它提供方便的形式,能像访问电脑文件一样访问到XML中的节点。首先我们看看XPath的一些要点。
本节要点
//1.XPath表达式
//2.IE和W3C使用XPath的差异
//3.alert()和console.log()的差别,alert()执行了obj.toString()
//4.正则表达式test,exec,replace和RegExp.$1的用法
//5.原型.__proto__和prototype的用法
1.XPath语法(源于W3SHOOL)
XML代码
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
我们以这段XML为例,讲述XPath表达式的用法。
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点。 |
/ | 从根节点选取。 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 |
. | 选取当前节点。 |
.. | 选取当前节点的父节点。 |
@ | 选取属性。 |
实例
路径表达式 | 结果 |
---|---|
bookstore | 选取 bookstore 元素的所有子节点。 |
/bookstore | 选取根元素 bookstore。 注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于 bookstore 的子元素的所有 book 元素。 |
//book | 选取所有 book 子元素,而不管它们在文档中的位置。 |
bookstore//book | 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。 |
//@lang | 选取名为 lang 的所有属性。 |
谓语用来查找某个特定的节点或者包含某个指定的值的节点。
谓语被嵌在方括号中。
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于 bookstore 子元素的第一个 book 元素。 |
/bookstore/book[last()] | 选取属于 bookstore 子元素的最后一个 book 元素。 |
/bookstore/book[last()-1] | 选取属于 bookstore 子元素的倒数第二个 book 元素。 |
/bookstore/book[position()<3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang='eng'] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
2.利用XPath获取节点和节点集
IE下的XPath
//IE浏览器下的XPath
//IE浏览器的XPath只有两个方式:
//IE9之后貌似不支持以下写法,出现“SCRIPT438: 对象不支持“selectNodes”属性或方法”的错误,解决方法是
//在菜单->工具->选择IE9兼容视图。
//selectSingleNode和selectNodes分别代表查找单个和多个节点
//查找的node数组从0开始
//XPath要和上下文对象相对应。
//xmlDom.documentElement.selectSingleNode("ROOT/PERSON/AGE");是错误的
var xmlDom = getXMLDom("<ROOT><PERSON ID='1'><NAME>user01</NAME><AGE>20</AGE></PERSON><PERSON ID='2'><NAME>user02</NAME><AGE>24</AGE></PERSON><PERSON ID='3'><NAME>user03</NAME><AGE>26</AGE></PERSON></ROOT>");
var node = xmlDom.selectNodes("ROOT/PERSON");
//xmlDom.selectSingleNode("ROOT/PERSON[0]"); //表示第一个节点
//xmlDom.selectSingleNode("ROOT/PERSON[AGE>24]"); //返回AGE大于24的节点
//xmlDom.selectSingleNode("ROOT/PERSON[@ID=2]"); //返回ID=2的节点
//node.firstChild.nodeValue; //利用标准DOM获取其中数据。注意获得的是字符串,在进行数学运算时要转化
//node[0].selectSingleNode("NAME"); //XPath和上下文对应
W3C下的XPath
//W3C中的XPath
//W3C中XPath数组用1开始,这是和IE不同的
//evaluate(xpathText,contextNode,namespaceURLMapper,resultType,result);
//其中5个参数的具体含义是
//xpathtext:表示要计算的XPath表达式的字符串
//contextNode:文档中,对应要计算的表达式的节点,上下文节点。
//namespaceURLMapper:把一个命名空间前缀映射为一个全称命名空间URL的函数。如果不需要就设为null
//resultType:指定了期待作为结果的对象的类型,使用XPath转换来强制结果类型。类型的可能的值是XPathResult对象所定义的常量。
//result:一个复用的XPathResult对象,如果你要创建一个新的XPathResult对象,则为null
//resultType有10个常量;其中FIRST_ORDERED_NODE_TYPE和ORDERED_NODE_ITERATOR_TYPE最为常用
/*
ANY_TYPE
把这个值传递给 Document.evaluate() 或 XPathExpression.evaluate() 来指定可接受的结果类型。属性 resultType 并不设置这个值。
NUMBER_TYPE
numbervalue 保存结果。
STRING_TYPE
stringvalue 保存结果。
BOOLEAN_TYPE
booleanValue 保存结果。
UNORDERED_NODE_ITERATOR_TYPE
这个结果是节点的无序集合,可以通过重复调用 iterateNext() 直到返回 null 来依次访问。在此迭代过程中,文档必须不被修改。
ORDERED_NODE_ITERATOR_TYPE
结果是节点的列表,按照文档中的属性排列,可以通过重复调用 iterateNext() 直到返回 null 来依次访问。在此迭代过程中,文档必须不被修改。
UNORDERED_NODE_SNAPSHOT_TYPE
结果是一个随机访问的节点列表。snapshotLength 属性指定了列表的长度,并且 snapshotItem() 方法返回指定下标的节点。节点可能和它们出现在文档中的顺序不一样。既然这种结果是一个“快照”,因此即便文档发生变化,它也有效。
ORDERED_NODE_SNAPSHOT_TYPE
这个结果是一个随机访问的节点列表,就像 UNORDERED_NODE_SNAPSHOT_TYPE,只不过这个列表是按照文档中的顺序排列的。
ANY_UNORDERED_NODE_TYPE
singleNodeValue 属性引用和查询匹配的一个节点,如果没有匹配的节点则为 null。如果有多个节点和查询匹配,singleNodeValue 可能是任何一个匹配节点。
FIRST_ORDERED_NODE_TYPE
singleNodeValue 保存了文档中的第一个和查询匹配的节点,如果没有匹配的节点,则为 null。
*/
//获取单一节点
var xmlDom = getXMLDom("<ROOT><PERSON ID='1'><NAME>user01</NAME><AGE>20</AGE></PERSON><PERSON ID='2'><NAME>user02</NAME><AGE>24</AGE></PERSON><PERSON ID='3'><NAME>user03</NAME><AGE>26</AGE></PERSON></ROOT>");
var result = xmlDom.evaluate("ROOT/PERSON[1]",xmlDom,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
console.log(result); //返回的是undefined.这里应该是火狐的问题,因为result的类型和值都不是undefined
//console.log(result.toString()); //返回的是[object XPathResult]
//alert(result); //返回的却是[object XPathResult]
//这说明alert()输出的全是字符串,他将自动调用Obj.toString();在调试时要注意两种方法的配合使用
if(result !== null){
serializeXML(result.singleNodeValue); //单一节点
}
//获取节点集
var xmlDom = getXMLDom("<ROOT><PERSON ID='1'><NAME>user01</NAME><AGE>20</AGE></PERSON><PERSON ID='2'><NAME>user02</NAME><AGE>24</AGE></PERSON><PERSON ID='3'><NAME>user03</NAME><AGE>26</AGE></PERSON></ROOT>");
var result = xmlDom.evaluate("ROOT/PERSON",xmlDom,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
var nodes = [];
var next =result.iterateNext();
while(next != null){
nodes.push(next);
next =result.iterateNext();
}
IE和W3C获取节点和节点集的封装
function serializeXML(xmlDom){
var xml = null;
//DOM2序列化xmlDom
if(typeof window.XMLSerializer != "undefined"){
xml = (new XMLSerializer).serializeToString(xmlDom);
}else if(typeof xmlDom.xml != "undefined"){
//IE序列化XMLDOM
xml = xmlDom.xml;
}
return xml;
}
function getXMLDom(xmlStr){
var xmlDom = null;
//DOM2获取xmlDom
if(typeof window.DOMParser != "undefined"){
xmlDom = (new DOMParser).parseFromString(xmlStr,"text/xml");
var errors = xmlDom.getElementsByTagName("parsererror");
if(errors.length > 0){
throw new Error("DOMParser错误!错误信息 :" + errors[0].textContent);
}
}else if(typeof window.ActiveXObject != "undefined"){
//IE获取xmlDom
var version = ["MSXML2.DOMDocument6.0","MSXML2.DOMDocument3.0","MSXML2.DOMDocument"];
for(var i = 0; i < version.length; i++){
try{
xmlDom = new ActiveXObject(version[i]);
}catch(e){
}
}
xmlDom.loadXML(xmlStr);
if(xmlDom.parseError != 0){
throw new Error("IEparseDom错误!错误信息 :" + xmlDom.parseError.reason);
}
}
return xmlDom;
}
//跨浏览器获取单一节点和节点集的封装
//1.获取单一节点
function getSingleNode(xpath,xmlDom){
var node = null;
//先判断W3C
if(typeof XPathEvaluator != "undefined"){
var result = xmlDom.evaluate(xpath,xmlDom,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null);
node = result.singleNodeValue;
}else{
//兼容低版本IE
//IE低版本数组从0开始
/\[(\d)\]/g.exec(xpath);
var num = RegExp.$1;
xpath = xpath.replace(num,parseInt(num) + 1);
node = xmlDom.selectSingleNode(xpath);
}
return node;
}
//2.获取节点集
function getNodes(xpath,xmlDom){
var nodes = [];
//先判断W3C
if(typeof XPathEvaluator != "undefined"){
var result = xmlDom.evaluate(xpath,xmlDom,null,XPathResult.ORDERED_NODE_ITERATOR_TYPE,null);
var node = null;
while((node = result.iterateNext()) != null){
nodes.push(node);
}
}else{
//兼容低版本IE
/\[(\d)\]/g.exec(xpath);
var num = RegExp.$1;
xpath = xpath.replace(num,parseInt(num) + 1);
nodes = xmlDom.selectNodes(xpath);
}
return nodes;
}
今天家里有点事,不能学很多。最近很多事影响着我。暑假让我明白一个道理,人是由内向外的,内心是本质,它将潜移默化的影响你。总之,做一个敞亮的人!