My xml file looks like this:
<run>
<address addr="64.233.189.104" addrtype="ipv4" />
<hostnames>
<hostname name="google.com" type="user"/>
<hostname name="hkg01s01-in-f104.1e100.net" type="PTR"/>
</hostnames>
<address addr="207.46.197.32" addrtype="ipv4" />
<hostnames>
<hostname name="microsoft.com" type="user"/>
</hostnames>
</run>
and my desired output is:
host|addr|PTR
google.com|64.233.189.104|hkg01s01-in-f104.1e100.net
microsoft.com|207.46.197.32
What I have unsuccessfully attempted is:
xml sel -t -m "//hostname" -v "@name" -o "|" -n test.xml
&
$ xml sel -t -m "//hostname" -v "@name" -o "|" -m "//address" -v "@addr" -n test.xml
But this falls short. Very short of the mark. TIA.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi - Thank you for the help here. It is very useful. I will try to dissect the line and fully understand what you have written. The condition statements you wrote:
-i "position() < 2"
and
-i "position() < last()"
remain admittedly somewhat elusive.
What I am trying to do here is use xmlstarlet to parse Nmap xml output files. It may be that Nmap does not output xml perfectly as you suggested, however it does validate. If you could tweak your xml statement to handle output the same thing as above but apply it to an actual Nmap scan (below), that would be most appreciated.
<?xml version="1.0" ?><?xml-stylesheet href="file:///opt/local/share/nmap/nmap.xsl" type="text/xsl"?><!-- Nmap 5.21 scan initiated Wed Jun 30 18:02:54 2010 as: nmap -p80 -oX scanme.xml scanme.nmap.org localhost --><nmaprunscanner="nmap"args="nmap -p80 -oX scanme.xml scanme.nmap.org localhost"start="1277895774"startstr="Wed Jun 30 18:02:54 2010"version="5.21"xmloutputversion="1.03"><scaninfotype="syn"protocol="tcp"numservices="1"services="80"/><verboselevel="0"/><debugginglevel="0"/><hoststarttime="1277895774"endtime="1277895774"><statusstate="up"reason="echo-reply"/><addressaddr="64.13.134.52"addrtype="ipv4"/><hostnames><hostnamename="scanme.nmap.org"type="user"/><hostnamename="ptr.scanme.nmap.org"type="PTR"/></hostnames><ports><portprotocol="tcp"portid="80"><statestate="open"reason="syn-ack"reason_ttl="247"/><servicename="http"method="table"conf="3"/></port></ports><timessrtt="256487"rttvar="197903"to="1048099"/></host><hoststarttime="1277895774"endtime="1277895774"><statusstate="up"reason="localhost-response"/><addressaddr="127.0.0.1"addrtype="ipv4"/><hostnames><hostnamename="localhost"type="user"/><hostnamename="ptr.localhost"type="PTR"/></hostnames><ports><portprotocol="tcp"portid="80"><statestate="closed"reason="reset"reason_ttl="64"/><servicename="http"method="table"conf="3"/></port></ports><timessrtt="66"rttvar="5000"to="100000"/></host><runstats><finishedtime="1277895774"timestr="Wed Jun 30 18:02:54 2010"elapsed="0.60"/><hostsup="2"down="0"total="2"/><!-- Nmap done at Wed Jun 30 18:02:54 2010; 2 IP addresses (2 hosts up) scanned in 0.60 seconds --></runstats></nmaprun>
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This does work! Mostly….
The xml above that I posted lost the last 3 lines:
<runstats><finishedtime="1277895774"timestr="Wed Jun 30 18:02:54 2010"elapsed="0.60"/><hostsup="2"down="0"total="2"/><!-- Nmap done at Wed Jun 30 18:02:54 2010; 2 IP addresses (2 hosts up) scanned in 0.60 seconds --></runstats></nmaprun>
Does this resolve the single root element issue you bring up?
Getting back to your code here, there are actually multiple elements for os/osclass with -v @type, so I get many different pipes with all the values. How do I limit this to just the first value?
You have been a big help, and I really appreciate it.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
One issue arises which is that if an element is empty, the extra "|" does not appear, which then makes the columns change proper alignment. I get output like:
This is good stuff. You introduced the square brackets in this iteration which seems to strengthen the structure of the output. I will experiment with this command line a bit more. Thanks again!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Beautiful! Works!
Also now that I have an example that works against my file, I understand better how to form the template.
Thanks for your rapid responses and awesome help.
Have a good weekend.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
My xml file looks like this:
<run>
<address addr="64.233.189.104" addrtype="ipv4" />
<hostnames>
<hostname name="google.com" type="user"/>
<hostname name="hkg01s01-in-f104.1e100.net" type="PTR"/>
</hostnames>
<address addr="207.46.197.32" addrtype="ipv4" />
<hostnames>
<hostname name="microsoft.com" type="user"/>
</hostnames>
</run>
and my desired output is:
host|addr|PTR
google.com|64.233.189.104|hkg01s01-in-f104.1e100.net
microsoft.com|207.46.197.32
What I have unsuccessfully attempted is:
xml sel -t -m "//hostname" -v "@name" -o "|" -n test.xml
&
$ xml sel -t -m "//hostname" -v "@name" -o "|" -m "//address" -v "@addr" -n test.xml
But this falls short. Very short of the mark. TIA.
Hi!
First of all I think that you organized your XML file incorrectly.
It should be like this:
And then the command line should be:
Hi - Thank you for the help here. It is very useful. I will try to dissect the line and fully understand what you have written. The condition statements you wrote:
and
remain admittedly somewhat elusive.
What I am trying to do here is use xmlstarlet to parse Nmap xml output files. It may be that Nmap does not output xml perfectly as you suggested, however it does validate. If you could tweak your xml statement to handle output the same thing as above but apply it to an actual Nmap scan (below), that would be most appreciated.
What do you think about this?
Or maybe this one that will format the output the way you prefer:
That's it! They both work. Now I tried to add another element to this: osclass/type, but it is not as straightforward as it seems:
Also, in the first example above, I have no idea how you output 2 pipes in output but only have one pipe in the one liner.
The element osclass/type was not in the previous xml sample. Here is another xml file where it is present:
The correct command line should be
But still, I don't think that it will work, because the xml file you demonstrate doesn't have a single root element.
This does work! Mostly….
The xml above that I posted lost the last 3 lines:
Does this resolve the single root element issue you bring up?
Getting back to your code here, there are actually multiple elements for os/osclass with -v @type, so I get many different pipes with all the values. How do I limit this to just the first value?
You have been a big help, and I really appreciate it.
Yes, the xml file is now complete and valid.
Thanks again…This looks very understandable. I extended this a little with:
One issue arises which is that if an element is empty, the extra "|" does not appear, which then makes the columns change proper alignment. I get output like:
For a correct pipe delimited output, the following would be preferable:
Thanks
If you need correct piped output then the following you should follow the following format:
which is the result of this command line
Assuming that you have one "hostname" with type "user" and zero or one hostnames with type "PTR".
This is good stuff. You introduced the square brackets in this iteration which seems to strengthen the structure of the output. I will experiment with this command line a bit more. Thanks again!
Couldn't find how to start my own question, please forgive.
I have a files that looks like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ResourcesResponse>
<Status>Success</Status>
<Resource id="14555" name="/var/log/messages-Monitor" description="monitor /var/log/messages" location="" instanceId="12833" typeId="3">
<ResourcePrototype resourceTypeId="3" instanceId="10109" id="10122" name="FileServer File"/>
<ResourceInfo key="autoIdentifier" value="/var/log/messages-Monitor"/>
</Resource>
<Resource id="14554" name="Control" description="this demonstrates a user-defined control" location="" instanceId="12832" typeId="3">
<ResourcePrototype resourceTypeId="3" instanceId="10109" id="10123" name="FileServer File"/>
<ResourceInfo key="autoIdentifier" value="Control"/>
</Resource>
</ResourcesResponse>
I am trying to sel ONLY the data for ResourceInfo@value when //Resource/Resource[@id=10122 not 10123.
I've tried many (100's) combinations but the closest form using '-C' looks to be:
xml sel -t -m //Resource -m "ResourcePrototype" -v "ResourceInfo/@value"
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="//Resource">
<xsl:for-each select="ResourcePrototype">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="ResourceInfo/@value"/>
</xsl:call-template>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template name="value-of-template">
<xsl:param name="select"/>
<xsl:value-of select="$select"/>
<xsl:for-each select="exslt:node-set($select)">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
but I can't seem to get output for ResourceInfo@value
TIA for your help.
I see an Add Topic button at the bottom of the forum's topic list page.
Thank you for your reply.
My eyes must have been crossed from looking at this too long and didn't see the Add button.
I tried the command above and received no output. It appears that it should be found by the output of the -C option.
~/scripting$ xml sel -t -v "//Resouce/ResourceInfo/@value" myFileResources.xml
~/scripting$ xml sel -C -t -v "//Resouce/ResourceInfo/@value" myFileResources.xml
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="//Resouce/ResourceInfo/@value"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="value-of-template">
<xsl:param name="select"/>
<xsl:value-of select="$select"/>
<xsl:for-each select="exslt:node-set($select)">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Oops, I had a silly typo.
Beautiful! Works!
Also now that I have an example that works against my file, I understand better how to form the template.
Thanks for your rapid responses and awesome help.
Have a good weekend.