With a slight modification to your XML, wrap all your XML in a parent <DATA>
tag1, or another one of your choosing, file called data.xml
:
<DATA>
<HARDWARE>
<NAME>WIN1</NAME>
<OS>Windows 7</OS>
<IP>1.2.3.4</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
<HARDWARE>
<NAME>WIN2</NAME>
<OS>Windows 8</OS>
<IP>10.20.30.40</IP>
<DOMAIN>contoso.com</DOMAIN>
</HARDWARE>
</DATA>
Using xmlstarlet
+ column
xmlstarlet sel -T -t -m /DATA/HARDWARE -v "concat(NAME,' ',OS,' ',IP,' ',DOMAIN)" -n data.xml | column -t
gives:
WIN1 Windows 7 1.2.3.4 contoso.com
WIN2 Windows 8 10.20.30.40 contoso.com
Edit:
Based on Peter.O's great catch in the comments and his answer below, let's send pipe delimited2 output to column -ts$'|'
, so something like:
xmlstarlet sel --indent-tab -T -t -m /DATA/HARDWARE -v "concat(NAME,'|',OS,'|',IP,'|',DOMAIN)" -n data.xml | column -ts$'|'
Now, the fields line up nicely even if they have spaces:
WIN1 Windows 7 1.2.3.4 release 5 contoso.com
Really long OS X Windows 8 10.20.30.40 contoso.com
1. Or use { echo '<DATA>'; cat file_name; echo '</DATA>'; } | xmlstarlet ...
as Peter.O notes in the comment below
2. Using space as the delimiter does not align the columns properly