XML parentNode属性无法识别,XPath结合JS解析遇问题
解析XML时获取父节点的问题解决
问题背景
本人是XML和JS新手,现尝试解析XML并收集所有<name>节点(后续需存入表格)。待解析的XML片段如下:
<?xml version="1.0" encoding="UTF-8"?> <model-data> <identification> <date>Thu Dec 15 14:43:07 CET 2022</date> <xml-version>4.11</xml-version> </identification> <model> <named-domains> <named-domain> <name>boolean</name> <elements> <element> <value>0</value> <name>No</name> <description>No</description> </element> <element> <value>1</value> <name>Yes</name> <description>Yes</description> </element> </elements> </named-domain> <named-domain> <name>D_NOME_TECNICO_COMPLETO</name> <elements> <element> <value>0</value> <name>PippoBaudo</name> <description>Superstar</description> </element> ... // same pattern </elements> </named-domain> </named-domains> </model> </model-data>
现有JS代码
<!DOCTYPE html> <html> <body> <p id="demo"></p> <script> var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { showResult(xhttp.responseXML); } }; xhttp.open("GET", "prova.xml", true); xhttp.send(); function showResult(xml) { var txt = ""; // path = "//named-domain/name[text()]"; path = "/model-data/model/named-domains//name[text()]"; if (xml.evaluate) { var nodes = xml.evaluate(path, xml, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); var result = nodes.iterateNext(); while (result) { txt += "<b>" + result.childNodes[0].nodeValue + "</b><br>"; result = nodes.iterateNext(); parente = nodes.parentnode.nodevalue; // <- Here something goes wrong! } // Code For Internet Explorer } else if (window.ActiveXObject || xhttp.responseType == "msxml-document") { xml.setProperty("SelectionLanguage", "XPath"); nodes = xml.selectNodes(path); for (i = 0; i < nodes.length; i++) { txt += nodes[i].childNodes[0].nodeValue + "<br>"; } } document.getElementById("demo").innerHTML = txt; } </script> </body> </html>
遇到的问题
- VS Code未提示
nodes有parentnode属性; - 强制写入后出现报错:
Uncaught TypeError: Cannot read properties of undefined (reading 'nodeValue')。
解决方案
错误原因分析
nodes是XPathResult迭代器对象,不是DOM节点,因此它本身没有parentNode属性;- 属性名写法错误:DOM节点的父节点属性是驼峰式的
parentNode,不是小写的parentnode;nodeValue同样需要驼峰写法。
修正后的代码逻辑
要获取当前<name>节点的父节点,需要从迭代到的result(当前DOM节点)上获取,而不是从nodes迭代器获取。同时要注意调用iterateNext()的时机——应该先处理当前节点的父节点,再获取下一个节点。
以下是修正后的showResult函数核心部分:
function showResult(xml) { var txt = ""; path = "/model-data/model/named-domains//name[text()]"; if (xml.evaluate) { var nodes = xml.evaluate(path, xml, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); var result = nodes.iterateNext(); while (result) { var nameValue = result.childNodes[0].nodeValue; txt += "<b>" + nameValue + "</b><br>"; // 获取当前name节点的直接父节点 var parentNode = result.parentNode; txt += "直接父节点:" + parentNode.nodeName + "<br>"; // 如果需要找到所属的<named-domain>节点(针对element下的name) if (parentNode.nodeName === "element") { var namedDomainNode = parentNode.parentNode.parentNode; var domainName = namedDomainNode.querySelector("name").textContent; txt += "所属域:" + domainName + "<br>"; } // 迭代下一个节点 result = nodes.iterateNext(); } } else if (window.ActiveXObject || xhttp.responseType == "msxml-document") { xml.setProperty("SelectionLanguage", "XPath"); nodes = xml.selectNodes(path); for (i = 0; i < nodes.length; i++) { var nameValue = nodes[i].childNodes[0].nodeValue; txt += nameValue + "<br>"; var parentNode = nodes[i].parentNode; txt += "直接父节点:" + parentNode.nodeName + "<br>"; } } document.getElementById("demo").innerHTML = txt; }
额外建议
- 如果只需要
<named-domain>下的<name>节点,可以修改XPath表达式为/model-data/model/named-domains/named-domain/name,避免获取到<element>下的<name>; - 可以使用
result.textContent替代result.childNodes[0].nodeValue,更简洁且兼容性更好。
内容的提问来源于stack exchange,提问作者PaNicorp
相关产品推荐
相关产品推荐

