【问题标题】:Split XML into chunks of 5 each using XPATH使用 XPATH 将 XML 拆分为 5 个块
【发布时间】:2018-11-07 05:38:33
【问题描述】:

我正在寻找 XPATH 表达式,它将 XML 拆分为每个 5 个元素的块。这是否可以通过单个 XPATH 表达式实现,因为我使用的工具只接受单个类似表达式而不接受 XSLT。类似按 5 个左右分组的东西。

【问题讨论】:

  • 听起来像是 XSLT-2.0 功能 xsl:for-each-group 的任务。
  • 是的,我知道。但是这个愚蠢的工具只接受 XPATH 表达式,而不接受 XSLT。他们讨厌简单的生活:)
  • 该工具支持哪个版本的 XPath?您如何期望纯 XPath 来构造结果,即分隔组?这对于 XQuery 或 XSLT 来说几乎是一项工作,除非您有 XPath 3.1 和映射/数组来创建一些结果结构。
  • 它支持3.0。我认为这是无法通过 xpath 实现的,我正在源代码本身做一个解决方法。谢谢大家。

标签: xml xslt xpath transformation


【解决方案1】:

例如,使用 XPath 3.1,您至少可以以某种方式将结果构造为包含 5 个元素的块

let $items := root/item,
    $size := 5
return
    for $i in (1 to count($items))[position() mod $size = 1]
    return array{$items[position() = ($i to ($i + $size - 1))]}

返回一个数组序列,其中每个数组都有$size 项(分别是最后一个数组剩余的项)。

https://xqueryfiddle.liberty-development.net/eiQZDbd 显示结果(请注意,该工具支持 XQuery 3.1,您可以使用更简单有效的方式进行分组和窗口化,但我尝试编写纯 XPath 3.1 表达式)。

不同的结果是单个数组,其中每个项目都是$size 元素的序列,例如

declare namespace array = "http://www.w3.org/2005/xpath-functions/array";

array:join(
    let $items := root/item,
        $size := 5
    return
    for $i in (1 to count($items))[position() mod $size = 1]
    return [$items[position() = ($i to ($i + $size - 1))]]
)

declare 又是 XQuery,对于纯 XPath 3.1,您需要使用特定于 API 的方式或者可能是确保声明数组函数的命名空间的工具。

【讨论】:

    【解决方案2】:

    如果您的工具只接受 XPath 1.0,那么您可以将 position() 用作 //item[(position()=1) or (position() <= 5)],然后将条件转换为 6,10 等。

    xmllint --xpath '//item[(position()=1) or (position() <= 5)]' test.xml | sed -re 's%(</[^>]+>)%\1\n%g'
    

    结果

    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
    

    【讨论】:

      猜你喜欢
      • 2017-02-22
      • 2017-10-30
      • 2017-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 1970-01-01
      • 2020-05-06
      相关资源
      最近更新 更多