xmlxpathxmlstarlet

How can I use xmlstarlet and XPath to extract two elements at the same time


I have an xml document of the form

root
 +- foo
 +- bar
 |   +- @baz

I want to extract the value of /root/foo and of /root/bar/@baz in one go from the command line.

I can do

cat file.xml | xmlstarlet sel -t -v "/root/foo" -n

and

cat file.xml | xmlstarlet sel -t -v "/root/bar/@baz" -n

separately.

And I can do

cat file.xml | xmlstarlet sel -t -v "/root/foo|bar/@baz" -n

which gives me the value of baz if foo doesn't exist.

I tried

cat file.xml | xmlstarlet sel -t -v "/root/[foo and bar/@baz]" -n

but that doesn't work

compilation error: element with-param
XSLT-with-param: Failed to compile select expression '/root/[foo and bar/@baz]'

How can I get both?

Update: Minimum reproducible example

XML File

<root>
  <foo>Value F1</foo>
  <bar baz="Value B1" />

  <foo>Value F2</foo>
  <bar baz="Value B2" />
</root>

The command

cat file.xml | xmlstarlet sel -t -v "/root/foo" -n

Gives me

Value F1
Value F2

and

cat file.xml | xmlstarlet sel -t -v "/root/bar/@baz" -n

Gives me

Value B1
Value B2

and

cat file.xml | xmlstarlet sel -t -v "/root/foo|bar/@baz" -n

Also gives me

Value F1
Value F2

My expected outcome is something like

Value F1 Value B1
Value F2 Value B2

each in one line.

I am using xmlstarlet, version

1.6.1
compiled against libxml2 2.9.13, linked with 20913
compiled against libxslt 1.1.35, linked with 10135

I don't care which version of XPath I need to use to get this outcome.


Solution

  • You were almost there with:

    /root/foo|bar/@baz
    

    try this:

    root/foo|/root/bar/@baz