Home > database >  xmlstarlet match/parsing by attribute instead of element
xmlstarlet match/parsing by attribute instead of element

Time:11-18

I have a complex structured XML file from which I'm trying to parse some values, using xmlstartlet. I think the issue is that the logical objects are identified by element attributes and not the actual element names.

The file test.xml, simplified for this example, looks like this:

<?xml version="1.0" encoding="utf-8"?>
<configDump>
  <cluster top-level-assembly="XYZ12312312312">
  </cluster>
  <views>
    <view status="ok" name="ABC">
      <viewInitiators>
        <viewInitiator id="ABCi1"></viewInitiator>
        <viewInitiator id="ABCi2"></viewInitiator>
      </viewInitiators>
      <viewPorts>
        <viewPort id="ABCp1"></viewPort>
        <viewPort id="ABCp2"></viewPort>
      </viewPorts>
      <viewVolumes>
        <viewVolume lun="1" id="ABCv1"></viewVolume>
        <viewVolume lun="2" id="ABCv2"></viewVolume>
      </viewVolumes>
    </view>
    <view status="ok" name="DEF">
      <viewInitiators>
        <viewInitiator id="DEFi1"></viewInitiator>
        <viewInitiator id="DEFi2"></viewInitiator>
      </viewInitiators>
      <viewPorts>
        <viewPort id="DEFp1"></viewPort>
        <viewPort id="DEFp2"></viewPort>
      </viewPorts>
      <viewVolumes>
        <viewVolume lun="1" id="DEFv1"></viewVolume>
        <viewVolume lun="2" id="DEFv2"></viewVolume>
      </viewVolumes>
    </view>
  </views>
</configDump>

I'm trying to generate output with fields that look like:

<top-level-assembly>-<view-name>,<viewInitiator-ID>

When I run the following:

xmlstarlet sel -t \
                -m //cluster \
                        --var sn=@top-level-assembly \
                -m //views/view \
                        --var view=@name \
                -m //views/view/viewInitiators/viewInitiator \
                        -v 'concat($sn,"-",$view,",",@id)' -n test.xml

I get the following output:

XYZ12312312312-ABC,ABCi1
XYZ12312312312-ABC,ABCi2
XYZ12312312312-ABC,DEFi1
XYZ12312312312-ABC,DEFi2
XYZ12312312312-DEF,ABCi1
XYZ12312312312-DEF,ABCi2
XYZ12312312312-DEF,DEFi1
XYZ12312312312-DEF,DEFi2

As you can seem I am getting all the "initiator" values under each "view", and not just the ones that are in that structure in the XML. I was expecting and hoping to get just:

XYZ12312312312-ABC,ABCi1
XYZ12312312312-ABC,ABCi2
XYZ12312312312-DEF,DEFi1
XYZ12312312312-DEF,DEFi2

Any thoughts on what I'm doing wrong?

CodePudding user response:

Any thoughts on what I'm doing wrong?

The -m options nest - to xsl:for-each statements - so you're asking for all viewInitiator/@ids for each view. To see the generated XSLT code add a -C option before -t.

The desired output can be generated by:

xmlstarlet sel -t \
    --var sn='configDump/cluster/@top-level-assembly' \
    -m '//viewInitiator' \
       -v 'concat($sn,"-",../../@name,",",@id)' -n \
< file.xml
  • Related