XmlSlurper: изменение текста в элементе с пространством имен

Я не понимаю, почему xml."con:cred"."ser:user" = "modified_username" не меняет текст. Кто-нибудь может это объяснить?

input = """
<kuk:acc xmlns:kuk="kuk">
    <con:cred xmlns:con="http://www.bea.com/wli/sb/resources/config">
        <ser:user xmlns:ser="http://www.bea.com/wli/sb/services">username</ser:user>
    </con:cred>
</kuk:acc>
"""

def xml = new XmlSlurper(keepWhitespace:true).parseText(input).declareNamespace(
    ser:"http://www.bea.com/wli/sb/services",
    con:"http://www.bea.com/wli/sb/resources/config")
println xml."con:cred"."ser:user" 

xml."con:cred"."ser:user" = "modified_username" // That doesn't work
println xml."con:cred"."ser:user" 

xml.cred.user = "modified_username" // That works
println xml."con:cred"."ser:user" 

/*
def outputBuilder = new StreamingMarkupBuilder() 
String result = outputBuilder.bind{ mkp.yield xml }
println result
*/

person shuttle    schedule 13.01.2012    source источник
comment
Как ни странно, если вы позвоните xml."con:cred"."ser:user".replaceBody( "modified_username" ) напрямую, это сработает ... Я бы подумал о том, чтобы опубликовать это в списке рассылки groovy-user, чтобы узнать, есть ли у кого-нибудь представление о том, что происходит ...   -  person tim_yates    schedule 13.01.2012


Ответы (1)


Я копался в этой проблеме некоторое время и собирался спросить то же самое. Учитывая, что при использовании перегруженного оператора '=' вызывается метод putAt(int, Object), более внимательно рассмотрим код GPathResult:

public void putAt(final int index, final Object newValue) {
    final GPathResult result = (GPathResult)getAt(index);

    if (newValue instanceof Closure) {
        result.replaceNode((Closure)newValue);
    } else {
        result.replaceBody(newValue);
    }
}

показывает, что replaceBody должен быть вызван. Как указывает *tim_yates*, replaceBody работает хорошо, поэтому кажется, что вместо этого вызывается replaceNode (я не понимаю, почему). Копаемся в NodeChildren replaceNode мы могу видеть это

protected void replaceNode(final Closure newValue) {
    final Iterator iter = iterator();
    while (iter.hasNext()) {
        final NodeChild result = (NodeChild) iter.next();
        result.replaceNode(newValue);
    }
}

закрытие никогда не вызывается, поэтому при вызове replaceNode ничего не делается. Поэтому я думаю, что в replaceNode есть ошибка (она ничего не делает), и при выполнении xml."con:cred"."ser:user" = "modified_username" правая часть выражения оценивается как замыкание (мне нужна помощь в этом вопросе, чтобы понять, почему :-).

person jalopaba    schedule 16.01.2012
comment
Интересно, что xml."con:cred"."ser:user"[0] = "modified_username_index" тоже работает - person Carl Pritchett; 27.01.2015