Groovy markupBuilder обновляет родительский узел

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

 def writer = new StringWriter()
 def xml = new MarkupBuilder(writer)

 xml.parent(totalDuration: 'should be: some of all child duration') {
     child(duration: '1')
     child(duration: '2') 
...  
 }

Есть ли элегантный способ доступа к родительскому узлу из дочернего узла?

Спасибо Тал

1 ответ

Решение

Есть ли элегантный способ доступа к родительскому узлу из дочернего узла?

Не с MarkupBuilder, который генерирует XML в потоковом режиме (он уже записал открывающий тег родительского элемента в выходной поток перед вызовом вложенного замыкания). Но вы можете использовать DOMBuilder для построения дерева DOM в памяти, затем заполнить итоговое значение с помощью DOM API и, наконец, сериализовать дерево DOM, включая атрибут total:

import groovy.xml.*
import groovy.xml.dom.*
import org.w3c.dom.*

def dom = DOMBuilder.newInstance(false, true)
Element parent = dom.parent() {
  child(duration:'1')
  child(duration:'2')
}
use(DOMCategory) {
  parent.setAttributeNS(null, "totalDuration",
                        parent.xpath('sum(child/@duration)'))
}

def xmlString = XmlUtil.serialize(parent)

DOMBuilder должен работать так же, как и MarkupBuilder, если вы не используете mkp.yield или же mkp.yieldUnescaped внутри закрытия. Если вам нужно использовать их, вам придется создать строку XML без totalDuration атрибута, затем повторно проанализируйте его в DOM, добавьте дополнительный атрибут и повторно сериализуйте.

Другие вопросы по тегам