【问题标题】:How to flatten XML with xmlstarlet?如何使用 xmlstarlet 展平 XML?
【发布时间】:2023-01-26 07:37:48
【问题描述】:

我有一个要展平的 XML 文件。

输入.xml:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item id="item1">
        <property name="mykey" value="keyname1"/>
        <property name="myval" value="value1"/>
    </item>

    <item id="item2">
        <property name="mykey" value="keyname2"/>
        <property name="myval" value="value2"/>
    </item>

    <item id="item3">
        <property name="mykey" value="keyname3"/>
        <property name="myval" value="value3"/>
    </item>
</items>

期望的输出:

<?xml version="1.0" encoding="UTF-8"?>
<items>
    <item id="item1" key="keyname1" value="value1" />
    <item id="item2" key="keyname2" value="value2" />
    <item id="item3" key="keyname3" value="value3" />
</items>

问题:我怎样才能用xmlstarlet做到这一点?

【问题讨论】:

  • 在单个命令中可能不可能。 An answer 类似的问题,但使用 xmllint

标签: xml xmlstarlet


【解决方案1】:

所需的输出可以由xmlstarlet edit产生:

xmlstarlet edit 
  -s '*/*' -t attr -n key -v '' 
  -u '$prev' -x 'string(../property[@name="mykey"]/@value)' 
  -s '*/*' -t attr -n value -v '' 
  -u '$prev' -x 'string(../property[@name="myval"]/@value)' 
  -d '*/*/property' 
file.xml
  • 不像-s (--subnode)-v (--value)-x (--expr)条款 -u (--update) 选项采用 XPath 参数,因此 两步法
  • $prev变量指的是最近创建的节点 -s-i-a 选项,它们都定义或重新定义它(请参阅 xmlstarlet.txt 例如 $prev
  • */*可以替换为items/item

xmlstarlet select

xmlstarlet select --xml-decl -E 'UTF-8' --indent -t 
  -e '{name(*)}' 
    -m '*/*' 
      -e '{name()}' 
        -a 'id' -v '@id' -b 
        -a 'key' -v '*[@name="mykey"]/@value' -b 
        -a 'value' -v '*[@name="myval"]/@value' 
file.xml
  • -e (--elem) 发出一个元素(这里使用 XSLT attribute value template)
  • -a (--attr) 发出一个属性,其 -v (--value) 子句采用 XPath 参数
  • *[@name="…"] 可以替换为 property[@name="…"](并且必须 用于 以外的 XML 解析器,如果没记错的话)
  • */*可以替换为items/item

(假设使用 POSIX shell 语法。)

【讨论】:

    猜你喜欢
    • 2015-11-25
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多