【问题标题】:XPath: get everything between two empty nodesXPath:获取两个空节点之间的所有内容
【发布时间】:2018-05-23 18:38:50
【问题描述】:

我需要编写一个 xpath expr 来获取空节点 (pb) 和下一次出现的 pb 之间的所有内容(节点和文本)。

我可以在 pb 节点之后获取“所有内容”,直到使用此查询的 XML 文件结束:

 //pb/following::*|//pb/following::text()

但我想将“单个”结果按 pb 分组到下一个 pb。

例子:

...
<pb/>
<elementX>text here </elementX>     --|
<moreElements/>                       |    Group 1
Plain text here without element     --|
<pb/>
<elementY>text here </elementY>     --|    Group 2
...                                 --|
<pb/>
...                                 --|    Group 3
EOF                                 --|

所以我想要 2 个 pb 之间的所有内容并将其分组。对于此示例,应该有 3 个结果组。从第一个 pb 到第二个的所有元素都应该在第一组中。从第二个 pb 到第三个 pb 是第二组。从第三个pb到最后应该还有第三组。

很难用语言来形容。需要更多信息吗?

如何告诉 xpath 在哪里结束并对结果进行分组?

提前致谢。

【问题讨论】:

    标签: xml xpath xquery


    【解决方案1】:

    如果你想创建组,XPath 是不够的(因为结果总是一个平面序列)。 XQuery 1.0 解决方案如下所示:

    for $pb in //pb
    let $next-pb := $pb/following-sibling::pb[1]
    return element group {
      $pb/following-sibling::node()[empty($next-pb) or . << $next-pb]
    }
    

    如果您的处理器支持 XQuery 3.0,您可以使用更高效的窗口子句:

    declare context item := document {
      <xml>
        <pb/>
        <elementX>text here </elementX>
        <moreElements/>
        Plain text here without element
        <pb/>
        <elementY>text here </elementY>
        ...
        <pb/>
        x
      </xml>
    };
    for tumbling window $w in /xml/node()
        start $s when name($s) = 'pb'
        end $e when name(head($e/following-sibling::node())) = 'pb'
    return element group { tail($w) }
    

    【讨论】:

    • 谢谢克里斯蒂安。遗憾的是,XQuery 3.0 无法正常工作……您测试了吗?我想我必须更多地了解 xquery 语言。 ;-)
    • 是的,我做到了(我使用了 BaseX)。您使用的是哪个处理器?
    • 我正在使用撒克逊语。 (HE/PE/EE 9.8.0.9)
    • 谢谢。我刚刚尝试了 Saxon(HE 9.8.0.6J 和 EE 9.8.0.12J),成功了;查询结果与 BaseX 相同。您能否详细说明一下您的情况“不工作”是什么意思?
    • 感谢您的测试。很抱歉在我的第一条评论中如此不具体......“请求”提供了一个空序列。
    【解决方案2】:

    正如 Christian 所指出的,XPath 只能提供节点集(或节点序列),因此无法进行任何分组。在两个里程碑标签&lt;start/&gt;&lt;end/&gt; 之间传递节点也很棘手(但并非不可能)。在 XPath 1.0 中你可以这样做:

    start/following-sibling::node()[following-sibling::end]
    

    但是对于长输入序列,它可能会非常低效。使用 XQuery 窗口或 XSLT 分组的解决方案更令人满意。

    【讨论】:

      猜你喜欢
      • 2023-03-31
      • 1970-01-01
      • 1970-01-01
      • 2012-02-15
      • 2015-10-29
      • 2019-04-19
      • 2015-07-24
      • 1970-01-01
      • 2023-03-27
      相关资源
      最近更新 更多