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
选项。
我有一个输入 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
选项。