Get xmllint to output xpath results \n-separated, for attribute selector
Asked Answered
S

5

25

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" />

Sleuth answered 31/7, 2013 at 8:17 Comment(6)
Does this help -- echo 'cat /config/*/@*[starts-with(name(),"key")]' | xmllint --shell input.xmlLifework
@devnull: | grep = and it's fine. (actually, no [starts-with()... just /@* I used "key1, key2..." as metasyntactic variables, the actual attribute names would be arbitrary.)Sleuth
Yes, grep -v and done!Lifework
@devnull: I'd prefer inclusive grep (all desired lines contain =, and undesired are rather fixed: / > cat /config/*/@* and ` -------` - and it's possible the value might contain -------, so grep '=' is sure to find what I want (unless I use = in the selector, which I don't.)Sleuth
@devnull: By the way, post that as an answer and I'll accept.Sleuth
Value only: #26824236Scranton
L
16

You can try:

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

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

Lifework answered 31/7, 2013 at 13:37 Comment(1)
Agree with Guss. Also I could work around parsing the diagnostics and the separator lines (with a different XPATH expression in my case), xmllint --shell /tmp/tt.xml <<< "cat //s/text()" | { read -r diag; while { read -r separator; read -r line; } ; do echo "${line}" ; done ; } > /tmp/tt-words.txtMozell
G
6

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

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

Galliard answered 26/5, 2015 at 3:19 Comment(0)
V
1

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 "
Venerable answered 4/5, 2015 at 14:44 Comment(1)
The problem of this is that it depends on consistent naming scheme of the keys (properties). If they are not 'key1, key2' but 'name, birthdate', this won't work.Sleuth
C
1

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.

Complected answered 30/7, 2018 at 14:37 Comment(2)
the commit link is deadBerar
@Berar movedComplected
W
1

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"
Wanderoo answered 7/11, 2019 at 11:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.