【问题标题】:extract xml nodes as table with xmlstarlet使用 xmlstarlet 将 xml 节点提取为表
【发布时间】:2021-02-10 10:47:10
【问题描述】:

我有一个非常简单但巨大的 xml(超过 50.000 行)。我只想提取一个重复的节点作为表(环)。考虑到这是一个例子。真实文件在“环”节点内有 300 多个元素,所以如果可能的话,我尽量避免逐个元素地编写提取命令。

这里有一个小例子

<xml>
<root>
  <ration>
    <ring>
      <id  value="1"/>
      <date  value="2021-01-01"/>
      <price  value="435"/>
    </ring>
  </ration>
</root>
<root>
  <ration>
    <ring>
      <id  value="14"/>
      <date  value="2021-02-01"/>
      <price  value="745"/>
    </ring>
  </ration>
</root>
</xml>

我想要实现的是: 这个 xmlstarlet 命令正在工作,我得到了正确的结果,但现在考虑执行 300 次(对于每个元素,我必须将调用插入 concat 部分)。我需要一个更简单的方法。

xmlstarlet sel -T -t -m '//root/ration/ring' -v "concat(id/@value,',',date/@value,',',price/@value)"  -n file.xml

id, date, price
1, 2021-01-01, 435
14, 2021-02-01, 745

【问题讨论】:

  • 我认为你不能用 xmlstarlet(它只支持 xpath 1.0)来做到这一点,但它可以用 xpath 2.0 及更高版本来完成——如果有的话,比如 xidel。
  • 尝试了一些方法,但最后,我用 xmlstarlet 查询所有元素名称,在 bash 中编写一个 concat 查询并执行查询

标签: xml xmlstarlet


【解决方案1】:

您已经有一段时间没有问过了。不过……

xmlstarlet sel -T \
    -t -m '//root[1]/ration/ring/*[boolean(@value)]' \
    -v 'substring(", ", 1, 2*(position() != 1))' -v 'local-name()' -b -nl \
    -t -m '//root' -m 'ration/ring/*[boolean(@value)]' \
    -v 'substring(", ", 1, 2*(position() != 1))' -v '@value' -b -nl \
    file.xml

输出:

id, date, price
1, 2021-01-01, 435
14, 2021-02-01, 745

模板#1 发出标头,#2 发出数据。 -m 表达式 #1 和 #3 匹配具有 @value 属性的 ring 的子元素。一起使用-m-b 可以解决问题。如果@value@* 替换,则所有属性都被选中;可以微调 @*[name()="value" or name()="otherval"] 等谓词的选择。

值的分离在 XSLT 1.0 中比在 2.0 中需要更多的工作:在这种情况下,substring 函数调用为第一个值返回一个空字符串,其中position() != 1 为假(转换为数字 0),以及一个 2-以下为真 (1) 的字符串(逗号和空格)。

顺便说一句,以xml 开头的任何低/高组合的标记/PI 名称都是reserved

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多