2

I have an xml, let's call it example.xml that looks like this:

<a>
  <b ref="lala">text of node b
  </b>
  <c ref="hihi">text of node c
  </c>
  <d somethingelse="foo">text of the node d
  </d>
</a>

I want to get the names of all the nodes that have an attribute called "ref"

so my output would be:

b
c

I have tried: xmlstarlet sel -t -v "name(//*[@ref])" example.xml but I only get the name of the first node as an output i.e., b. What is missing in my command to get all the node names?

Note: I run on debian bulleyes and here is my xmlstarlet version:

xmlstarlet --version
1.6.1
compiled against libxml2 2.9.10, linked with 20910
compiled against libxslt 1.1.34, linked with 10134
pyoupyou
  • 55
  • 6
  • This command is almost making it: **xmlstarlet sel -t -m "//*[@ref]" -v "name()" example.xml** it gets me "bc", I just wish it output it not concatenated to a single line. – pyoupyou Feb 23 '22 at 13:33
  • Some other post seem to have similar problems of single vs multiple output for instance: https://stackoverflow.com/questions/6390807/why-doesnt-xmlstarlet-select-all-nodes – pyoupyou Feb 23 '22 at 13:35

2 Answers2

1

Found something that seems to work:

xmlstarlet sel -t -m "//*[@ref]" -v "name()" -n example.xml

The -n is the tag to give the output on different lines.

It might have been a problem of version (not sure). Anyway this post about unique vs multiple output with xmlstarlet gave me some help:

Why doesn't xmlstarlet select all nodes?

pyoupyou
  • 55
  • 6
0

Try this one to get names of nodes with "ref" attribute:

//*[@ref]/name()
JaSON
  • 4,843
  • 2
  • 8
  • 15
  • You mean **xmlstarlet sel -t -v "//*[@ref]/name()" example.xml** ? I get an error **Invalid expression: //*[@ref]/name() compilation error: element with-param XSLT-with-param: Failed to compile select expression '//*[@ref]/name()'** – pyoupyou Feb 23 '22 at 13:10
  • @pyoupyou this is weird. Do you get different output with `//*[@ref]/local-name()`? – JaSON Feb 23 '22 at 13:15
  • same error with **xmlstarlet sel -t -v "//*[@ref]/local-name()" example.xml** I get: **Invalid expression: //*[@ref]/local-name()...** – pyoupyou Feb 23 '22 at 13:18
  • @pyoupyou I guess my expression applicable for XPath 2.0 only... Try to get list of `"//*[@ref]"` first and then make a loop with `"./name()"` – JaSON Feb 23 '22 at 13:36
  • Found the answer. Your remark was halfway to the solution since my version of xmlstarlet seems to prefer an approach like yours. – pyoupyou Feb 23 '22 at 13:54