Get xmllint to output xpath results \\n-separated,

2020-02-11 17:52发布

问题:

How can I get xmllint to output multiple results of xpath selector for attributes "per line"?

Take this example:

  <?xml version="1.0" encoding="ISO-8859-1"?>
  <config>
          <tagX key1="value1 " key2=" value2"/>
          <tagY key3="value3" key4=" value4 "/>
  </config>


  $ xmllint example.xml --xpath "/config/*/@*"

The result is:

   key1="value1 " key2=" value2" key3="value3" key4=" value4 "

What I'd like to get is:

   key1="value1 "
   key2=" value2"
   key3="value3"
   key4=" value4 "

Would I need to split after even-numbered quote marks, or is there any neater way to do this?

There's a related question, about the same subject except it's about picking out contents of <tag>value</tag>, and not <tag attribute="value" />

回答1:

You can try:

$ xmllint --shell inputfile <<< `echo 'cat /config/*/@*'`

You might need to grep the output, though, so as to filter the undesired lines.



回答2:

If it's an option, try using xmlstarlet instead:

xmlstarlet sel -t -v "/config/*/@*" example.xml



回答3:

The question is old but as I came to this post searching a solution to the same problem, here is my solution

On linux add sed substitution to split output:

$ xmllint example.xml --xpath "/config/*/@*" | sed "s| key|\nkey|g"

of course the substitution expression depends on your xml structure and your xpath query.

And you can even add line numbers on each line if you add nl

$ xmllint example.xml --xpath "/config/*/@*" | sed "s| key|\nkey|g" | nl

Which gives

   1 key1="value1 "
   2 key2=" value2"
   3 key3="value3"
   4 key4=" value4 "


回答4:

I found that Ubuntu v.14 and v.18 use too old libxml2 versions. So i solved the issue mentioned in the topic by the recompiling of libxml2 v2.9.10.

1) Download the sources of libxml2 from http://linuxfromscratch.org/blfs/view/cvs/general/libxml2.html

2) Download the test suite:

$ wget http://www.w3.org/XML/Test/xmlts20130923.tar.gz

3) Execute:

$ tar xf libxml2-2.9.10.tar.gz

4) Execute:

$ cd libxml2-2.9.10/

5) Execute:

$ sed -i 's/test.test/#&/' python/tests/tstLastError.py

6) Execute:

$ export CPATH="/usr/include/python3.6/:$CPATH"

7) Execute:

$ sudo apt-get install -y python3-libxml2 python3-pip

8) Execute:

$ sudo pip3 install libxml2dom

9) Execute:

$ ./configure --prefix=/usr --disable-static --with-history --with-python=/usr/bin/python3 && make

Ensure here that the returning code ($?) is 0.

10) Execute:

$ tar xf ../xmlts20130923.tar.gz

11) Execute:

make check > check.log

Ensure here that the returning code ($?) is 0.

12) Execute:

$ sudo make install

Enjoy

$ xmllint data.xml -xpath "//some_child/ancestor::some_parent/attribute::id"                                                                               
 id="1"
 id="10010"
 id="10011"
 id="10020"
 id="10021"


回答5:

If using the latest xmllint, results should have been separated by \n now. However, if fields contain \n, you can use this patched version to use \0 as a separator, with --xpath0. For whatever reason the PR hasn't been merged yet.