jsonxmlgroovyxmlslurperjsonbuilder

Nested XML to flat JSON using groovy


I am still new to groovy. I need to create a flat json file from a nested xml file. I am having a hard time accessing the header fields when I try to create the JSON.

this is the input:

<?xml version="1.0"?>
<Data>
<Record>
    <Header>Header01</Header>
    <Item>
        <TEST>E1</TEST>
        <TEST2>Free text</TEST2>
    </Item>
</Record>
<Record>
    <Header>Header02</Header>
    <Item>
        <TEST>E2</TEST>
        <TEST2>Free text</TEST2>
    </Item>
    <Item>
        <TEST>E3</TEST>
        <TEST2>Free text</TEST2>
    </Item>
</Record>

Here is my code:

def xml = new XmlSlurper().parse(reader)
def RecordList = xml.'*'.findAll { it->it.name() == 'Record' }
def itemlist = RecordList.'*'.findAll{node ->node.name()== 'Item'}.collect{
    row -> row.collectEntries{[TEST: row.TEST.text(), TEST2:row.TEST2.text()]}
}

StringWriter writer = new StringWriter()
StreamingJsonBuilder builder = new StreamingJsonBuilder(writer)

builder {
    "Records" itemlist
}

println JsonOutput.prettyPrint(writer.toString())

Output:

  {"Records":[{"TEST":"E1","TEST2":"Free text"},{"TEST":"E2","TEST2":"Free text"}, 
  {"TEST":"E3","TEST2":"Free text"}]}

how do I populate the header fields using this method? by the time I create the list of items, I no longer have access to the header fields in the xml.


Solution

  • Not 100% what you mean...

    Do you mean this:

    def result = new XmlParser().parse(reader)
        .Record
        .collectMany { record ->
            record.Item.collect {
                [ Header: record.Header.text(), Test: it.TEST.text(), Test2: it.TEST2.text() ]
            }
        }
    
    println new JsonBuilder(result).toPrettyString()
    

    Which prints:

    [
        {
            "Header": "Header01",
            "Test": "E1",
            "Test2": "Free text"
        },
        {
            "Header": "Header02",
            "Test": "E2",
            "Test2": "Free text"
        },
        {
            "Header": "Header02",
            "Test": "E3",
            "Test2": "Free text"
        }
    ]