Search code examples
xmlgroovyxmlslurper

How to get all the sub tags as list using XmlSlurper


I want to read all the variable names from an xml file. However while I would expecxt some sort of List I get all the "Names" glued together. How an I get all the Names in a List?

Xml:

<DataSet>
    <Version>1.0</Version>
    <DataSupplier>
    </DataSupplier>
    <Media>
        <Name />
        <Table>
            <URL>Sachkontenstamm.csv</URL>
            <Name>Sachkontenplan</Name>
            <DecimalSymbol>,</DecimalSymbol>
            <DigitGroupingSymbol />
            <VariableLength>
                <VariableColumn>
                    <Name>Ktonr</Name>
                    <Description>Kontonummer des Kontos</Description>
                    <Numeric />
                </VariableColumn>
                <VariableColumn>
                    <Name>Text</Name>
                    <Description>Beschriftung</Description>
                    <AlphaNumeric />
                    <MaxLength>40</MaxLength>
                </VariableColumn>
                ...
      </VariableLength>
              </Table>   
     </Media>
</DataSet>

groovy:

def indexFile = new XmlSlurper().parse(new File("src/main/resources/index.xml"))

indexFile
        .'**'
        .findAll { it?.URL == "Sachkontenstamm.csv" }
        .VariableLength
        .VariableColumn
        .Name

Solution

  • If you want to extract VariableColumn.Name correctly you need to collect all children nodes of VariableLength. In example you have shown above parser squashes path result to a single node. You can fix it by adding collect operation to VariableLength children and extracting information you are interested about. Consider following example:

    def xml = '''<DataSet>
        <Version>1.0</Version>
        <DataSupplier>
        </DataSupplier>
        <Media>
            <Name />
            <Table>
                <URL>Sachkontenstamm.csv</URL>
                <Name>Sachkontenplan</Name>
                <DecimalSymbol>,</DecimalSymbol>
                <DigitGroupingSymbol />
                <VariableLength>
                    <VariableColumn>
                        <Name>Ktonr</Name>
                        <Description>Kontonummer des Kontos</Description>
                        <Numeric />
                    </VariableColumn>
                    <VariableColumn>
                        <Name>Text</Name>
                        <Description>Beschriftung</Description>
                        <AlphaNumeric />
                        <MaxLength>40</MaxLength>
                    </VariableColumn>
                </VariableLength>
            </Table>   
         </Media>
    </DataSet>
    '''
    
    def indexFile = new XmlSlurper().parseText(xml)
    
    def result = indexFile.'**'
            .findAll { it?.URL == "Sachkontenstamm.csv" }
            .collect { it.VariableLength.'*'.findAll { node -> node.name() == 'VariableColumn' }*.Name*.text() }
            .flatten()
    
    assert result == ['Ktonr', 'Text']
    

    Hope it helps.