使用 XPath 获取 XML 元素的层次结构
Get the hierarchy of a XML element with XPath
我正在尝试获取“application/xml”response.data 文档中给定元素层次结构的有序列表,我在 [=24] 中使用 DOM 解析器对其进行了解析=].因此表达式应该 return 列表 ['Grand Parent','Parent','Target'] 对于每个没有 A 子标签的 A 标签。因此,我将获得一个列表列表,其中内部列表的最后一个元素将是 的最深(根据图形深度)值。
感谢@Jack Fleeting 我知道我可以使用下面的表达式 xpath 获取目标:
xpath = '//*[local-name()="A"][not(.//*[local-name()="A"])]/*[local-name()="A-title"]'
但我不确定如何调整它以进入层次结构列表。
<A>
<A-title>Grand Parent</A-title>
<A>
<A-title>Parent</A-title>
<A>
<A-title>Target</A-title>
</A>
</A>
</A>
编辑:
axios.get('WMS_URL').then((r) => {
const parser = new DOMParser()
const dom = parser.parseFromString(r.data, 'application/xml')
let xpath = '//*[local-name()="A"][not(.//*[local-name()="A"])]/*[local-name()="A-title"]'
let xpath2 = 'ancestor-or-self::A/A-title'
var targets = dom.evaluate(xpath, dom, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
var targets2 = dom.evaluate(xpath2, targets, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
Array.from({ length: targets2.snapshotLength }, (_, index) => layerNames.push(targets2.snapshotItem(index).innerHTML))
如果您使用 XPath //A[not(A)]/ancestor-or-self::A/A-title
,您会得到 //A[not(A)]
所有 A
没有 A
子元素的元素,下一步导航到所有祖先或自身 A
个元素,最后到所有 A-title
个子元素。当然,在带有单个表达式的 XPath 1 中,您无法构建字符串列表(或元素?)的列表,因此您首先需要 sel3ect //A[not(A)]
然后从那里 select ancestor-or-self::A/A-title
元素.
使用 XPath 3.1,例如 Saxon JS 2 (https://www.saxonica.com/saxon-js/index.xmlm, https://www.saxonica.com/saxon-js/documentation/index.html),您可以直接构建字符串数组序列,例如
//A[not(A)] ! array { ancestor-or-self::A/A-title/data() }
评估 XPath 的 JavaScript 代码是例如
let result = SaxonJS.XPath.evaluate('parse-xml($xml)//A[not(A)] ! array { ancestor-or-self::A/A-title/data() }', [], { params : { 'xml' : r.data }})
使用 DOM Level 3 XPath 1.0 我认为您需要更多的代码行:
let xmlDoc = new DOMParser().parseFromString(r.data, 'application/xml');
let leafAElements = xmlDoc.evaluate('//A[not(A)]', xmlDoc, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let result = [];
for (let i = 0; i < leafAElements.snapshotLength; i++) {
let titleEls = xmlDoc.evaluate('ancestor-or-self::A/A-title', leafAElements.snapshotItem(i), null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let titles = [];
for (let j = 0; j < titleEls.snapshotLength; j++) {
titles.push(titleEls.snapshotItem(j).textContent);
}
result.push(titles);
}
我正在尝试获取“application/xml”response.data 文档中给定元素层次结构的有序列表,我在 [=24] 中使用 DOM 解析器对其进行了解析=].因此表达式应该 return 列表 ['Grand Parent','Parent','Target'] 对于每个没有 A 子标签的 A 标签。因此,我将获得一个列表列表,其中内部列表的最后一个元素将是 xpath = '//*[local-name()="A"][not(.//*[local-name()="A"])]/*[local-name()="A-title"]'
但我不确定如何调整它以进入层次结构列表。
<A>
<A-title>Grand Parent</A-title>
<A>
<A-title>Parent</A-title>
<A>
<A-title>Target</A-title>
</A>
</A>
</A>
编辑:
axios.get('WMS_URL').then((r) => {
const parser = new DOMParser()
const dom = parser.parseFromString(r.data, 'application/xml')
let xpath = '//*[local-name()="A"][not(.//*[local-name()="A"])]/*[local-name()="A-title"]'
let xpath2 = 'ancestor-or-self::A/A-title'
var targets = dom.evaluate(xpath, dom, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
var targets2 = dom.evaluate(xpath2, targets, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null)
Array.from({ length: targets2.snapshotLength }, (_, index) => layerNames.push(targets2.snapshotItem(index).innerHTML))
如果您使用 XPath //A[not(A)]/ancestor-or-self::A/A-title
,您会得到 //A[not(A)]
所有 A
没有 A
子元素的元素,下一步导航到所有祖先或自身 A
个元素,最后到所有 A-title
个子元素。当然,在带有单个表达式的 XPath 1 中,您无法构建字符串列表(或元素?)的列表,因此您首先需要 sel3ect //A[not(A)]
然后从那里 select ancestor-or-self::A/A-title
元素.
使用 XPath 3.1,例如 Saxon JS 2 (https://www.saxonica.com/saxon-js/index.xmlm, https://www.saxonica.com/saxon-js/documentation/index.html),您可以直接构建字符串数组序列,例如
//A[not(A)] ! array { ancestor-or-self::A/A-title/data() }
评估 XPath 的 JavaScript 代码是例如
let result = SaxonJS.XPath.evaluate('parse-xml($xml)//A[not(A)] ! array { ancestor-or-self::A/A-title/data() }', [], { params : { 'xml' : r.data }})
使用 DOM Level 3 XPath 1.0 我认为您需要更多的代码行:
let xmlDoc = new DOMParser().parseFromString(r.data, 'application/xml');
let leafAElements = xmlDoc.evaluate('//A[not(A)]', xmlDoc, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
let result = [];
for (let i = 0; i < leafAElements.snapshotLength; i++) {
let titleEls = xmlDoc.evaluate('ancestor-or-self::A/A-title', leafAElements.snapshotItem(i), null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let titles = [];
for (let j = 0; j < titleEls.snapshotLength; j++) {
titles.push(titleEls.snapshotItem(j).textContent);
}
result.push(titles);
}