2
<annotation>
  <folder>cars_train</folder>
  <filename>00001.jpg</filename>
  <path>Users/hantaoliu/Documents/Research/cars_train/.jpg</path>
  <source>
    <database>Unknown</database>
  </source>
  <size>

The text above is one of the XML file I want to update. I have 7k XML files and I want the path of them to be:

Users/hantaoliu/Documents/Research/cars_train/$@.jpg

$@ corresponds to the name of the input file. For example, if the input file is 00001.xml, I want the path to be:

Users/hantaoliu/Documents/Research/cars_train/00001.jpg

I'm using xmlstarlet, but I'm not able to figure it out?

slm
  • 15,396
  • 12
  • 109
  • 124
Liu Hantao
  • 620
  • 1
  • 9
  • 19

1 Answers1

2

You can accomplish what you want like so. First select the value of filename and the value of path.

$ filenameVal=$(xmlstarlet sel -t -v "/annotation/filename" file)
$ pathVal=$(xmlstarlet sel -t -v "/annotation/path" file)

Next determine the directory name of path via the $(dirname $pathVal) and concatenate $filenameVal to it. You can do a test run of this without editing the file like so:

$ xmlstarlet ed -u "/annotation/path" -v "$(dirname $pathVal)/$filenameVal" file
<?xml version="1.0"?>
<annotation>
  <folder>cars_train</folder>
  <filename>00001.jpg</filename>
  <path>Users/hantaoliu/Documents/Research/cars_train/00001.jpg</path>
  <source>
    <database>Unknown</database>
  </source>
  <size>
  </size>
</annotation>

If things look good you can add the -L switch which tells xmlstartlet to edit in place.

$ xmlstarlet ed -L -u "/annotation/path" -v "$(dirname $pathVal)/$filenameVal" file

Confirming the results in file:

$ cat file
<?xml version="1.0"?>
<annotation>
  <folder>cars_train</folder>
  <filename>00001.jpg</filename>
  <path>Users/hantaoliu/Documents/Research/cars_train/00001.jpg</path>
  <source>
    <database>Unknown</database>
  </source>
  <size>
  </size>
</annotation>

References

slm
  • 15,396
  • 12
  • 109
  • 124
  • Do I have to enter every individual filename to the file? – Liu Hantao Sep 04 '18 at 04:23
  • For example, in this step $ filenameVal=$(xmlstarlet sel -t -v "/annotation/filename" file), Do I have to change the value of file in filenameVal if I am doing 00002.xml? – Liu Hantao Sep 04 '18 at 04:24
  • @LiuHantao - I wasn't sure what structure you had of the 7K files. You can use `find` or a Bash `for` loop to work through them and do the above. – slm Sep 04 '18 at 04:24
  • @LiuHantao - that's correct, the above is a template of the approach. You need to loop through it over all your files to accomplish this. – slm Sep 04 '18 at 04:25
  • How do I use a loop with xmlstarlet? A shell script? – Liu Hantao Sep 04 '18 at 04:26
  • @LiuHantao - correct, the looping would be handled by a shell script. – slm Sep 04 '18 at 04:26