【问题标题】:merge xml element attribute合并xml元素属性
【发布时间】:2020-05-14 09:26:42
【问题描述】:

我有一个输入 xml

<IndexCatalogueRecord SeriesNumber="1" SeriesVolume="3" SeriesPage="594">
<IndexCatalogueID>10305941390</IndexCatalogueID>
<GeneralNote>[Shelved in: B.58]</GeneralNote>
<GeneralNote>[Shelved in: B.458]</GeneralNote>
<GeneralNote>[Shelved in: B.20]</GeneralNote>
<Language>fr</Language>
</IndexCatalogueRecord>

我需要一个解决方案来组合由逗号分隔符分隔的 GeneralNote 元素属性,使其变为

<IndexCatalogueRecord SeriesNumber="1" SeriesVolume="3" SeriesPage="594">
<IndexCatalogueID>10305941390</IndexCatalogueID>
<GeneralNote>[Shelved in: B.58, B.458, B.20]</GeneralNote>
<Language>fr</Language>
</IndexCatalogueRecord>

我的方法是让 xmlstarlet 查询元素的属性值,然后通过管道将其通过 grep 或 awk 进行处理。我可以使用 xmlstarlet 轻松地从 GeneralNote 中获取属性的值

 xmlstarlet sel -t -m "//GeneralNote" -v . -n test.xml

但是当我尝试将控制台输出传递给 grep 以使其剥离匹配的字符串“[Shelved in:”和“]”时,我遇到了一些麻烦,如果有更优雅的解决方案,请告诉我。提前致谢

【问题讨论】:

    标签: xml xml-parsing xmlstarlet


    【解决方案1】:

    一种可能的方法是使用两个嵌套的xmlstarlet 命令
    (注意表达式中文件名的两次出现):

    xmlstarlet ed -u "/IndexCatalogueRecord/GeneralNote[1]" \
      -v "$(xmlstarlet sel -t -o "[Shelved in: " -m "/IndexCatalogueRecord/GeneralNote" \
      -v "substring-after(substring-before(.,']'),'[Shelved in: ')" \
      --if 'position() != last()' -o ', ' -b -b -o "]" input.xml)" \
      -d "/IndexCatalogueRecord/GeneralNote[position() > 1]" input.xml
    

    内部xmlstarlet 命令从所有 GeneralNote 元素创建最终值,外部命令更新第一个GeneralNote 元素并删除另一个。在xmlstarlet中ed是编辑值模式,sel是选择值模式。

    • -u - 表示更新值
    • -v - 通过 XPath 检索值
    • -m - 遍历与 XPath 表达式匹配的所有节点
    • -o - 输出一个静态字符串
    • -b - 结束迭代或 if 子句
    • -d - 删除与 XPath 匹配的所有节点

    如果您想修改 XML 就地,请在 xmlstarlet ed 之后添加一个 -L 选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-19
      • 1970-01-01
      • 1970-01-01
      • 2014-12-18
      相关资源
      最近更新 更多