How do I declare XPath namespaces in xmlstarlet?

I am new to xmlstarlet, so hope this answer is simple.

I am writing a script to modify Inkscape SVG files from the command line. I chose the xmlstarlet tool.

After testing the command syntax on test files, I am having problems with real SVG files. I think using namespaces throws me off.

Example file:

<?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>

      

I want to change Gradient6204

to Gradient9999

.

I wrote this command which doesn't work (just returns the original file).

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

      

I also tried again adding namespaces with -N, but no luck. I found that if I remove the line:

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

      

from a file, then the command I wrote above works.

What is the correct syntax to update the SVG file above as I described?

+3


source to share


1 answer


Explicit namespace declaration

Adding -N s=http://www.w3.org/2000/svg

and then using the namespace prefix s:

works:

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

      


Implicit default namespace declaration



Starting with XMLStarlet v1.2.1 , explicitly defining the command line for the default namespace (like the OP SVG file) can be avoided by automatically linking _

to the default namespace:

1.3. More convenient solution

XML documents can also use different namespace prefixes on any element in the document. To handle namespaces with greater ease, XMLStarlet (version 1.2.1+) will use the namespace prefixes declared in the root element of the input document. By default, the namespace will be bound to the prefixes _

and DEFAULT

(in versions 1.5.0+).

So the above command line can be rewritten as:

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

      

+4


source







All Articles