我想从 shell 添加命名空间前缀到 XML 文档的默认命名空间的标签

我想从 shell 添加命名空间前缀到 XML 文档的默认命名空间的标签

我有一个 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/选项(不在用户指南中,而是在--inplaceeditxmlstarlet.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更改节点名称的文字值。

相关内容