22

I am using windows version of xmlstarlet to update an xml file, via windows batch file.

xml edit --update "/xml/table/rec[@id=3]/@id" --value 10 %xmlfile%

I expected this to update the id attribute of rec node to 10. When I run this I see the updated xml as expected in the command line, but the file is never updated.

How can I do it, I want to stay away rewriting the whole file as the file could be big one.

before update:

<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1" />
    <rec id="2" />
    <rec id="3" />
  </table>
</xml>

after update:

<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1" />
    <rec id="2" />
    <rec id="10" />
  </table>
</xml>
Schu
  • 1,124
  • 3
  • 11
  • 23
  • 2
    most shell tools don't support updating data inplace.For example, the `sed -i` (inplace) option is still writing the data to a new place on disk and then deleting the old file. I think the same is true for XML tools. I'd be really surprized if `xmlstarlet` works any differently. Good luck. – shellter Mar 25 '15 at 20:32
  • Please show the XML document, before and after this update. – Mathias Müller Mar 25 '15 at 20:36
  • @Mathias I certainly agree with you in principle that it's good to show the input but the issue here is editing in-place. The file `
    ` is sufficient to reproduce the issue - the `id` attribute is modified but the output is printed to stdout, rather than back to the file.
    – Tom Fenech Mar 25 '15 at 20:42
  • @TomFenech I also agree with you, but sometimes the OP does not give reliable or complete information about what happens - for instance, the XML document might not be well-formed, but they did not mention that. – Mathias Müller Mar 25 '15 at 20:53

1 Answers1

39

You did not show your input document, but I assume it is the following, taken from the xmlstarlet documentation:

<xml>
  <table>
    <rec id="1">
      <numField>123</numField>
      <stringField>String Value</stringField>
    </rec>
    <rec id="2">
      <numField>346</numField>
      <stringField>Text Value</stringField>
    </rec>
    <rec id="3">
      <numField>-23</numField>
      <stringField>stringValue</stringField>
    </rec>
  </table>
</xml>

xmlstarlet modifies the file, but the result is sent to standard output, not saved in the original file. Use another option --inplace to modify the file in place:

$ xml ed --inplace -u "/xml/table/rec[@id='3']/@id" -v 5 rec.xml

Then:

$ cat rec.xml
<?xml version="1.0"?>
<xml>
  <table>
    <rec id="1">
      <numField>123</numField>
      <stringField>String Value</stringField>
    </rec>
    <rec id="2">
      <numField>346</numField>
      <stringField>Text Value</stringField>
    </rec>
    <rec id="5">
      <numField>-23</numField>
      <stringField>stringValue</stringField>
    </rec>
  </table>
</xml>

By the way, this question seems to ask something very similar to this question.


EDIT: As suggested by @npostavs, this option is listed in the edit help:

$ xml edit --help
...
-L (or --inplace)   - edit file inplace
...
Community
  • 1
  • 1
Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • thank you very much, mathias. that did the trick. i was looking for this option and couldnt find one in the api anywhere. how did you find this one? – Schu Mar 25 '15 at 20:55
  • @Schu It's indeed not part of the documentation, in my opinion. [Noam Postavsky briefly mentions it did not ship with the intial release](http://stackoverflow.com/a/18060194/1987598). – Mathias Müller Mar 25 '15 at 21:01
  • 2
    Careful with the namespaces. I had a namespace defined in my file and had to add `_:` before every element as [defined in the docs](http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html) in the section `1.3. A More Convenient Solution` – Leo Lozes Sep 08 '17 at 10:14
  • @LeoLozes Yes, if there are namespaces in your document, you have to take care of them. But the document in the question does not have namespaces, so there is no need. – Mathias Müller Sep 12 '17 at 12:14
  • Great comment! This --inplace option does not seem to be in the docs... – user2403232 Dec 04 '20 at 02:43