嵌套XML向上节点查询:已知Detail ID获取对应Item No方法
从指定Detail节点向上查找所属Item节点
问题背景
已通过以下代码定位到**Id属性值为“5”**的<Detail>节点:
const Detail_id= "5"; let xRes = xmlDoc.evaluate(`//Item/Details/Detail[@Id="${Detail_id}"]`, xmlDoc.documentElement);
需要从该节点向上遍历嵌套XML结构,找到其所属的<Item No="0002">节点。
对应XML结构
<xml> <Items> <Item No="0001"> <Details> <Detail Id="3"> <Colors> <Color colorName="green" /> <Color colorName="yellow" /> </Colors> </Detail> </Details> </Item> <Item No="0002"> <Details> <Detail Id="5"> <Colors> <Color colorName="purple" /> <Color colorName="pink" /> </Colors> </Detail> <Detail Id="6"> <Colors> <Color colorName="grey" /> <Color colorName="orange" /> </Colors> </Detail> </Details> </Item> </Items> </xml>
参考:向下查询指定Item的详情代码
以下代码可正常运行,用于获取<Item No="0002">的所有详情(包括Detail的Id及colorName属性值):
const SEARCH_NO = "0002"; let xRes = xmlDoc.evaluate(`//Item[@No="${SEARCH_NO}"]`, xmlDoc.documentElement); const foundNode = xRes.iterateNext(); if (foundNode) { xRes = xmlDoc.evaluate('Details/Detail', foundNode); let detailNode; while ( !!( detailNode = xRes.iterateNext() ) ) { const li = showDetail(detailNode.getAttribute("Id")); const colXres = xmlDoc.evaluate('Colors/Color/@colorName', detailNode); let colorTextNode; while ( !!( colorTextNode = colXres.iterateNext() ) ) { showColor(li, colorTextNode.textContent); } } }
解决方案
方法1:使用XPath的ancestor轴直接查询
利用XPath的祖先轴ancestor::Item[1],可以直接从已定位的Detail节点获取最近的父Item节点,代码如下:
const Detail_id= "5"; // 先定位到目标Detail节点 let xRes = xmlDoc.evaluate(`//Item/Details/Detail[@Id="${Detail_id}"]`, xmlDoc.documentElement); const detailNode = xRes.iterateNext(); if (detailNode) { // 查询最近的Item父节点 const itemXRes = xmlDoc.evaluate('ancestor::Item[1]', detailNode); const itemNode = itemXRes.iterateNext(); if (itemNode) { // 验证结果,输出Item的No属性 console.log(itemNode.getAttribute("No")); // 输出:0002 } }
说明:ancestor::Item[1]表示匹配当前节点的所有祖先节点中的第一个Item节点,也就是距离当前Detail节点最近的父Item节点,无需手动逐层遍历。
方法2:通过DOM节点的parentNode逐层向上遍历
如果需要手动控制遍历逻辑,可以通过节点的parentNode属性逐层向上检查节点名称,直到找到Item节点:
const Detail_id= "5"; // 先定位到目标Detail节点 let xRes = xmlDoc.evaluate(`//Item/Details/Detail[@Id="${Detail_id}"]`, xmlDoc.documentElement); const detailNode = xRes.iterateNext(); if (detailNode) { let currentNode = detailNode; // 逐层向上遍历,直到找到Item节点 while (currentNode && currentNode.nodeName !== "Item") { currentNode = currentNode.parentNode; } if (currentNode) { // 验证结果,输出Item的No属性 console.log(currentNode.getAttribute("No")); // 输出:0002 } }
说明:这种方法适合需要在遍历过程中添加额外判断逻辑的场景,比如中途需要检查其他节点类型。
内容的提问来源于stack exchange,提问作者Sarahrb
相关产品推荐
相关产品推荐

