Search code examples
xmlbatch-filexpathwindows-subsystem-for-linuxxmlstarlet

Selecting a tag base on another tag


When i have an xml file like this (named test.xml):

<root>
<item val="3"></item>
<items>
  <item>1</item>
  <item>2</item>
  <item>3</item>
  <item>4</item>
  <item>5</item>
  <item>6</item>
</items>
</root>

I can do this:

xmlstarlet sel -t -v /root/item/@val -o "," -v /root/items/item[3] test.xml which results in the output 3,3, which is OK. But when the value of /root/item/@val is changed then i do not want to change the command line for xmlstarlet.

How can i replace the 3 between the brackets for /root/item/@val ?

I tried: xmlstarlet sel -t -v /root/item/@val -o "," -v /root/items/item[/root/item/@val] test.xml

but that gives the following output:

3,1
2
3
4
5
6

I do have this problem on Windows, i could use wsl but a Windows solution is preferred ... 😉

EDIT: Based on the suggestion from @Cyrus):

this batch file gives the correct result:

@echo off
for /f "usebackq" %%f in (`xml sel -t -v /root/item/@val  test.xml`) do set a=%%f
xml sel -t -o "%a%," -v /root/items/item[%a%]  test.xml

But it still do hope there is a single line version of this.


Solution

  • Try using --var to set a variable containing @val and compare that against the position of the item...

    xmlstarlet sel -t --var val="/root/item/@val" -v "$val" -o "," -v "/root/items/item[number($val)]" test.xml
    

    Another, slightly shorter, alternative to /root/items/item[position()=$val] above...

    /root/items/item[number($val)]
    

    Note: Using number() makes your original attempt work too:

    xmlstarlet sel -t -v /root/item/@val -o "," -v /root/items/item[number(/root/item/@val)] test.xml
    

    Example of Windows cmd usage:

    enter image description here