Reputation: 23
I have the following xml:
<a>
<TICKET_LIST>
<TICKET>
<NUMBER>182820</NUMBER>
<DETECTION>
<IP network_id="173230">192.168.140.61</IP>
<DNSNAME><![CDATA[local]]></DNSNAME>
<PORT>80</PORT>
<SERVICE>CGI</SERVICE>
<PROTOCOL>tcp</PROTOCOL>
</DETECTION>
<VULNINFO>
<TITLE><![CDATA[HTTP TRACE / TRACK Methods Enabled]]></TITLE>
<TYPE>VULN</TYPE>
<QID>12680</QID>
<SEVERITY>3</SEVERITY>
<STANDARD_SEVERITY>3</STANDARD_SEVERITY>
<CVE_ID_LIST>
<CVE_ID><![CDATA[CVE-2004-2320]]></CVE_ID>
<CVE_ID><![CDATA[CVE-2010-0386]]></CVE_ID>
<CVE_ID><![CDATA[CVE-2003-1567]]></CVE_ID>
</CVE_ID_LIST>
</VULNINFO>
</TICKET>
<TICKET>
<NUMBER>182957</NUMBER>
<DETECTION>
<IP network_id="173230">192.168.200.46</IP>
<DNSNAME><![CDATA[local]]></DNSNAME>
<PORT>443</PORT>
<SERVICE>Web server</SERVICE>
<PROTOCOL>tcp</PROTOCOL>
</DETECTION>
<VULNINFO>
<TITLE><![CDATA[Web Server Uses Plain-Text Form Based Authentication]]></TITLE>
<TYPE>VULN</TYPE>
<QID>86728</QID>
<SEVERITY>3</SEVERITY>
<STANDARD_SEVERITY>3</STANDARD_SEVERITY>
</VULNINFO>
</TICKET>
</TICKET_LIST>
</a>
I would like to export some data to a csv format.
This code returns some the data as expected:
xmlstarlet sel -T -t -m /a/TICKET_LIST/TICKET -v "concat(NUMBER,',',DETECTION/IP,',',DETECTION/DNSNAME,',',DETECTION/SERVICE,',',DETECTION/PORT,',',VULNINFO/TITLE,',',VULNINFO/QID)" -n file.xml
However I am also interested in all CVE_ID data on the same line as the rest of the data.
Result I am getting now is:
182820,192.168.140.61,local,CGI,80,HTTP TRACE / TRACK Methods Enabled,12680
182957,192.168.200.46,local,Web server,443,Web Server Uses Plain-Text Form Based Authentication,86728
Expected results is:
182820,192.168.140.61,local,CGI,80,HTTP TRACE / TRACK Methods Enabled,12680,CVE-2004-2320 CVE-2010-0386 CVE-2003-1567
182957,192.168.200.46,local,Web server,443,Web Server Uses Plain-Text Form Based Authentication,86728
Upvotes: 2
Views: 520
Reputation: 52858
Since there are multiple CVE_ID
elements, you'll need to add another match (-m
) matching VULNINFO/CVE_ID_LIST/CVE_ID
.
Also, to get the newline (-n
) to output correctly you'll have to break nesting (-b
).
Example...
xmlstarlet sel -T -t -m /a/TICKET_LIST/TICKET -v "concat(NUMBER,',',DETECTION/IP,',',DETECTION/DNSNAME,',',DETECTION/SERVICE,',',DETECTION/PORT,',',VULNINFO/TITLE,',',VULNINFO/QID,',')" -m VULNINFO/CVE_ID_LIST/CVE_ID -v "concat(.,' ')" -b -n file.xml
Output...
182820,192.168.140.61,local,CGI,80,HTTP TRACE / TRACK Methods Enabled,12680,CVE-2004-2320 CVE-2010-0386 CVE-2003-1567
182957,192.168.200.46,local,Web server,443,Web Server Uses Plain-Text Form Based Authentication,86728,
The command line might make more sense if you see the XSLT that xmlstarlet uses internally (-C
)...
<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" method="text"/>
<xsl:template match="/">
<xsl:for-each select="/a/TICKET_LIST/TICKET">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="concat(NUMBER,',',DETECTION/IP,',',DETECTION/DNSNAME,',',DETECTION/SERVICE,',',DETECTION/PORT,',',VULNINFO/TITLE,',',VULNINFO/QID,',')"/>
</xsl:call-template>
<xsl:for-each select="VULNINFO/CVE_ID_LIST/CVE_ID">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="concat(.,' ')"/>
</xsl:call-template>
</xsl:for-each>
<xsl:value-of select="' '"/>
</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)[position()>1]">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Note that the second line of the output has a trailing ,
. I wouldn't think that would be an issue since the CSV rows would all have the same number of columns.
If it is a problem, you could use an "if" (-i
) and check to see if there are any CVE_ID
's before processing them...
xmlstarlet sel -T -t -m /a/TICKET_LIST/TICKET -v "concat(NUMBER,',',DETECTION/IP,',',DETECTION/DNSNAME,',',DETECTION/SERVICE,',',DETECTION/PORT,',',VULNINFO/TITLE,',',VULNINFO/QID)" -i VULNINFO/CVE_ID_LIST/CVE_ID -o "," -m VULNINFO/CVE_ID_LIST/CVE_ID -v "concat(.,' ')" -b -n file.xml
Output is the same as above except the trailing ,
is not output on the second line...
182820,192.168.140.61,local,CGI,80,HTTP TRACE / TRACK Methods Enabled,12680,CVE-2004-2320 CVE-2010-0386 CVE-2003-1567
182957,192.168.200.46,local,Web server,443,Web Server Uses Plain-Text Form Based Authentication,86728
Upvotes: 2