开发者

Selecting elements from xml file with xmlstarlet, can't quite get the syntax right

开发者 https://www.devze.com 2023-01-04 20:22 出处:网络
Here is the xml snippet: $ cat short.xml <hostnames> <hostname name=\"yahoo.com\" type=\"user\"/>

Here is the xml snippet:

$ cat short.xml 
<hostnames>
    <hostname name="yahoo.com" type="user"/>
    <hostname name="ir1.fp.vip.sp2.yah开发者_StackOverflow社区oo.com" type="PTR"/>
</hostnames>
<hostnames>
    <hostname name="Inc.com" type="user"/>
    <hostname name="www.inc.com" type="PTR"/>
</hostnames>

The desired output is:

yahoo.com | ir1.fp.vip.sp2.yahoo.com
Inc.com | www.inc.com

What I have so far that is only partially working: $ xml sel -t -m "//hostname" -v "@name" -n short.xml

I cannot seem to trap the Type= condition properly. TIA.


Two more solutions using xmlstarlet only once (no need to iterate):

xmlstr='
<root>
  <hostnames>
    <hostname name="yahoo.com" type="user"/>
    <hostname name="ir1.fp.vip.sp2.yahoo.com" type="PTR"/>
  </hostnames>
  <hostnames>
    <hostname name="Inc.com" type="user"/>
    <hostname name="www.inc.com" type="PTR"/>
  </hostnames>
</root>
'

echo "$xmlstr" | xmlstarlet sel -T -t -m "//hostnames" -m "hostname[@type='user']" -v '@name' -o " | " -b -m "hostname[@type='PTR']" -v '@name' -n

echo "$xmlstr" | xmlstarlet sel -T -t -m "//hostname" -i "@type='user'" -v '@name' -o " | " -b -i "@type='PTR'" -v '@name' -n


You need to count the hostnames with xmlstarlet el or something and then iterate with something like:

xmlstarlet sel -t -c "//hostnames[1]" short.xml | xmlstarlet sel -t -m "//hostname/@name" -v . -o ' | '

This would be a lot easier if the XML was better designed. :)


The example given in question is invalid xml.

xmlstarlet --version
1.3.1
compiled against libxml2 2.8.0, linked with 20800
compiled against libxslt 1.1.26, linked with 10126
xmlstarlet val -e short.xml 
short.xml:5.1: Extra content at the end of the document
<hostnames>
^
short.xml - invalid

The idea in the answer by mitm is quite nice cure.


$ xml sel -t -m //hostnames -v "concat(hostname[1]/@name,'|',hostname[2]/@name)" -n file.xml

$ xml sel -t -m //hostnames -v hostname[1]/@name -o "|" -v hostname[2]/@name -n file.xml

$ xml sel -t -m //hostname[@type='user'] -v @name -o "|" -v following-sibling::hostname/@name -n file.xml
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号