Использование внешней строковой переменной в Groovy Markup Builder

Я создал строковую переменную, используя некоторую логику в groovy, которая отражает синтаксис скобок в компоновщике разметки, но проблема в том, что вам явно не разрешено использовать эту строку в компоновщике разметки. Природа моего кода делает это необходимым. Я хочу знать, есть ли способ сделать что-то вроде следующего

def param = "node1{ node2{ node3() } }"
def sw = new StringWriter()
def xml = new groovy.xml.MarkupBuilder(sw)

XML = xml.param

Я знаю, что приведенный выше код неверен, но есть ли способ сделать то, к чему я клоню? Чтобы быть понятным, param - это строка, которая является продуктом другого куска кода. Я ищу, чтобы получить кусок XML, как показано ниже:

<node1><node2><node3/></node2><node1>

Спасибо

1 ответ

Решение

Если вы измените свое закрытие string быть (я назвал это builder поскольку я не заинтересован в именах классов в нижнем регистре в качестве имен свойств)

def builder = { ->
    node1 {
        node2{
            node3()
        }
    }
}

Затем вы можете сделать это с StreamingMarkupBuilder:

String output = new groovy.xml.StreamingMarkupBuilder().bind { 
    builder.delegate = delegate
    builder()
}.toString()

А также output будет содержать строку:

<node1><node2><node3/></node2></node1>

Редактировать:

Похоже, я неправильно понял и param переменная является строкой. В этом случае вы можете сделать это, чтобы оценить строку (завернутую в замыкание) и сделать то же самое, что и выше:

def param = "node1 { node2 { node3() } }"

String output = new groovy.xml.StreamingMarkupBuilder().bind { smb ->
    Eval.me( "{ -> $param }" ).with { c ->
        c.delegate = smb
        c()
    }
}.toString()

Следует отметить, однако, что следует соблюдать осторожность при выполнении каких-либо действий с Eval. Ему будет все равно, если код является вредоносным или неопасным, он просто запустит его, возможно, приведет к сбою приложения или удалению кода или, что еще хуже.

Может быть, вместо того, чтобы строить строку, вы могли бы построить карту или что-то? Тогда вы можете сделать что-то вроде этого:

def param = [ node1:[ node2:[ node3:'' ] ] ]

String output = new groovy.xml.StreamingMarkupBuilder().bind {
    param.each { k, v ->
        "$k" { v instanceof Map ? v.each( owner ) : mkp.yield( v ) }
    }
}
Другие вопросы по тегам