如何在xmlstarlet中声明XPath命名空间?

21

我对xmlstarlet还不熟悉,所以希望这个答案是简单的。

我正在编写一个脚本来从命令行修改Inkscape SVG文件,我选择了工具xmlstarlet。

在测试了测试文件的命令语法之后,我在真正的SVG文件上遇到了麻烦。我认为命名空间的使用让我感到困惑。

示例文件:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->    
<svg
   xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   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"
   width="603"
   height="1000"
   viewBox="0 0 159.54375 264.58334"
   version="1.1"
   id="svg8"
   inkscape:version="0.92.1 r"
   sodipodi:docname="test.svg"
   inkscape:export-filename="/home/user/dev/inkscape/test/1.png"
   inkscape:export-xdpi="96"
   inkscape:export-ydpi="96">
  <defs
     id="defs2">
    <linearGradient
       inkscape:collect="always"
       id="linearGradient6204">
      <stop
         style="stop-color:#8f1a22;stop-opacity:1;"
         offset="0"
         id="stop6200" />
      <stop
         style="stop-color:#8f1a22;stop-opacity:0;"
         offset="1"
         id="stop6202" />
    </linearGradient>
  </defs>
</svg>

我想将Gradient6204更改为Gradient9999

我写了这个命令,但它不起作用(只返回原始文件)。

xmlstarlet ed -u "/svg/defs/linearGradient[@id='linearGradient6204']/@id" -v 'linearGradient9999' text.txt

我也尝试了一下,使用-N添加命名空间但没有成功。我发现如果删除这行代码:

xmlns="http://www.w3.org/2000/svg"

如果从文件中读取,那么我上面写的命令可以正常工作。

更新上述SVG文件的正确语法是什么?

1个回答

31

显式命名空间声明

添加-N s=http://www.w3.org/2000/svg,然后使用s:命名空间前缀即可起作用:

xmlstarlet ed  -N s=http://www.w3.org/2000/svg -u "/s:svg/s:defs/s:linearGradient[@id='linearGradient6204']/@id" -v 'linearGradient9999' text.txt

隐式声明默认命名空间

XMLStarlet v1.2.1开始,可以通过将_自动绑定到默认命名空间来避免在命令行中显式定义默认命名空间(例如OP的SVG文件)。请看以下引用:

1.3 更为便利的解决方案

XML文档也可以在文档中的任何元素上使用不同的名称空间前缀。为了更轻松地处理名称空间, XMLStarlet(版本1.2.1+)将使用输入文档的根元素上声明的名称空间前缀。 默认名称空间将绑定到前缀_DEFAULT(在版本1.5.0+中)。

因此,上述命令行可以重写为:

xmlstarlet ed -u "/_:svg/_:defs/_:linearGradient[@id='linearGradient6204']/@id" -v 'linearGradient9999' text.txt

另请参阅


我不明白:输入文件中没有使用s:前缀;为什么需要定义这样的前缀才能使事情正常工作? - sdbbs
@sdbbs:重要的不是命名空间前缀(s:),而是它所绑定的命名空间名称(http://www.w3.org/2000/svg)。只要你使用的前缀绑定到正确的命名空间名称,你可以使用t:fred:代替s:。请参阅XML中命名空间和前缀的区别是什么?。另请参阅XPath如何处理XML命名空间? - kjhughes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接