![我想从 shell 添加命名空间前缀到 XML 文档的默认命名空间的标签](https://linux22.com/image/169511/%E6%88%91%E6%83%B3%E4%BB%8E%20shell%20%E6%B7%BB%E5%8A%A0%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E5%89%8D%E7%BC%80%E5%88%B0%20XML%20%E6%96%87%E6%A1%A3%E7%9A%84%E9%BB%98%E8%AE%A4%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4%E7%9A%84%E6%A0%87%E7%AD%BE.png)
我有一个 SVG 文件,它是一个 XML 文档:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
<defs
id="defs2">
<!-- a lot of stuff> </defs>
<!-- more stuff-->
</svg>
我想将 svg: 前缀添加到与默认命名空间对应的所有标签中,以获得下一个输出:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg:svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">
<svg:defs
id="defs2">
<!-- a lot of stuff> </svg:defs>
<!-- more stuff-->
</svg:svg>
我确信这可以在 shell 的一个或几个命令行中使用xmllint和/或xmlstarlet但我无法管理它。
答案1
自从你问起以来已经有一段时间了。尽管如此 ...
xmlstarlet edit
's -r
/--rename
操作需要新名称的文字值,因此 XPath 函数已不再适用。但是,xmlstarlet select
可以用作代码生成器来生成编辑命令:
xmlstarlet select -t \
--var sq -o "'" -b \
-o 'xmlstarlet edit --pf \' -n \
-m 'set:distinct(//_:*)' \
-o ' -r ' -v 'concat($sq,"//_:",local-name(),$sq)' \
-o ' -v ' -v 'concat($sq,"svg:",local-name(),$sq)' -o ' \' -n \
-b \
-f -n \
file.xml
在哪里
- 表达式
//_:*
匹配默认命名空间中的所有元素节点(_
快捷方式位于xmlstarlet
用户手册) - EXSLT 函数
set:distinct
消除重复 -o
输出字符串文字、-n
换行符、-f
输入路径名/URL(但-
对于标准输入)-b
结束当前容器(-m
,--var
不带=
,ao)- 在列出生成的 XSLT 代码之前添加一个
-C
选项-t
输出:
xmlstarlet edit --pf \
-r '//_:svg' -v 'svg:svg' \
-r '//_:defs' -v 'svg:defs' \
file.xml
在哪里
-P
/--pf
保留原始格式- 在支持就地编辑 后添加
-L
/选项(不在用户指南中,而是在--inplace
edit
xmlstarlet.txt)
要将输出作为 shell 脚本执行:
xmlstarlet-select-command | sh -s > result.xml
如果您想避免 EXSLT,请改为-m '//_:*' --sort 'A:T:-' .
通过管道输出uniq
,或者简单地-m '//_:*'
使用可能的重复项。
答案2
xmlstarlet
以特别残酷的方式使用(我等待正确的 xpath)
for x in $(xmlstarlet sel -t -m "//*" -n -v "name()" file1.xml | sort | uniq); do
xmlstarlet ed -r "//svg:$x" -v "svg:$x" file1.xml > tmp.xml;
mv tmp.xml file1.xml;
done
由于您已经声明了命名空间svg
,因此您需要在 中调用它来xpath
更改节点名称的文字值。