merge xml 元素属性

merge xml element attribute

我有一个输入 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:”和“]”时,我遇到了一些麻烦,如果有更优雅的解决方案,请告诉我。提前致谢

一种可能的方法是使用两个嵌套的 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 命令从 all GeneralNote 元素创建最终值,外部命令更新第一个 GeneralNote 元素并删除另一个。在xmlstarlet中,ed是编辑值模式,sel是select值模式。

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

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