xmlgroovymarkupbuilder

Groovy Markup-Builder use dynamic node name


I want to create a XML with the Markup-Builder in Groovy. I have the following XML in my program:

<root>
    <row>
        <first-name>Max</first-name>
        <last-name>Mustermann</last-name>
        <DEUcountry>DEU</DEUcountry>
        <DEUgenericString1>Generic-1 DEU</DEUgenericString1>
        <DEUgenericString2>Generic-2 DEU</DEUgenericString2>
    </row>
    <row>
        <first-name>Marlene</first-name>
        <last-name>Musterfrau</last-name>
        <USAcountry>USA</USAcountry>
        <USAgenericString1>Generic-1 USA</USAgenericString1>
        <USAgenericString2>Generic-2 USA</USAgenericString2>
    </row>
</root>

and i want to output something like this:

<root>
  <row>
    <D>Max</D>
    <D>Mustermann</D>
    <D>2000-01-01</D>
    <localcountry country='DEU'>DEU</localcountry>
    <localgenericString1 country='DEU'>Generic-1 DEU</localgenericString1>
    <localgenericString2 country='DEU'>Generic-2 DEU</localgenericString2>
  </row>
  <row>
    <D>Marlene</D>
    <D>Musterfrau</D>
    <D>2001-12-31</D>
    <localcountry country='USA'>USA</localcountry >
    <localgenericString1 country='USA'>Generic-1 USA</localgenericString1>
    <localgenericString2 country='USA'>Generic-2 USA</localgenericString2>
  </row>
</root>

Actually i'm figuring out the Country by a simple substring(0,3). But what i don't get, is to use a dynamic name with the Markup-Builder to be able to build "localcountry" for example.

My coding so far:

def writer = new StringWriter()
def builder = new MarkupBuilder(writer)
        
        builder.root{
            _root.row.each{_row ->
                row{
                    _row.childNodes().each{_node ->
                        if (_node.name().substring(0,3) == _node.name().substring(0,3).toUpperCase() &&
                            _node.text() != ""){
                            localized([country: _node.name().substring(0,3)],_node.text()){}
                        }else if (_node.name().substring(0,3) != _node.name().substring(0,3).toUpperCase()){
                            D(_node.text()){                  
                            }
                        }               
                    }
                }
            }
        }

        return writer.toString()

So the output is like:

<row>
    <D>Marlene</D>
    <D>Musterfrau</D>
    <D>2001-12-31</D>
    <localized country='USA'>USA</localized>
    <localized country='USA'>Generic-1 USA</localized>
    <localized country='USA'>Generic-2 USA</localized>
</row>

I don't understand how to become "localized" to be dynamic "localcountry", "localgenericString1" and so on, depending on the _node.


Solution

  • this is a function call in your code:

    localized ([country: _node.name().substring(0,3)],_node.text()) {}
    

    and in markup builder function name becomes a tag name.

    In groovy it's possible to call function by a dynamic name using interpolated string in place of a function name:

    "local${_node.name().substring(3)}" (...) {}