【问题标题】:Get the hierarchy of a XML element with XPath使用 XPath 获取 XML 元素的层次结构
【发布时间】:2021-07-29 23:12:04
【问题描述】:

我试图在“application/xml”response.data 文档中获取给定元素层次结构的有序列表,我使用 Javascript 中的 DOM 解析器解析该文档。因此,表达式应该为每个没有 A 子级的 A 标记返回列表 ['Grand Parent','Parent','Target']。所以我将得到一个列表列表,其中内部列表的最后一个元素将是 的最深(就图形深度而言)值。 感谢@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))

【问题讨论】:

    标签: javascript xml dom xpath dom-traversal


    【解决方案1】:

    如果你使用 XPath //A[not(A)]/ancestor-or-self::A/A-title 你会得到 //A[not(A)] 所有 A 元素没有 A 子元素,下一步导航到所有祖先或自我 A 元素,最后到所有 A-title 子元素.当然,在带有单个表达式的 XPath 1 中,您无法构建字符串列表(或元素?)列表,因此您首先需要选择 //A[not(A)],然后从那里选择 ancestor-or-self::A/A-title 元素。

    使用 XPath 3.1,例如使用 Saxon JS 2(https://www.saxonica.com/saxon-js/index.xmlmhttps://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); 
    }
    

    【讨论】:

    • 如果您使用 Saxon JS 2 而不是使用 DOMParser 和 XPath 1 evaluate 我会使用例如axios.get('WMS_URL').then((r) =&gt; { let result = SaxonJS.XPath.evaluate('parse-xml($xml)//A[not(A)] ! array { ancestor-or-self::A/A-title/data() }', [], { params : { 'xml' : r.data }}); })。然后,then 处理程序中的 result 变量是一个 JavaScript 数组,其中包含具有 A-title 值的字符串数组。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多