2015-08-05 4 views
0
  • У меня есть строка, которая содержит данные XML.
  • Мне нужно вставить новый узел в качестве дочернего элемента определенного узла (я знаю атрибут id для родителя)
  • Значение нового узла должно быть неэкранировано, когда я печатаю новые данные xml.

код:Редактирование строки XML с Groovy

String xmlSampleToEdit = ''' 
<sample> 
    <items> 
    <one id="1">ONE</one> 
    <ten id="10">TEN</ten> 
    <twenty id="20"></twenty> 
    </items> 
</sample> 
''' 
String newNodeValue = 'twenty&one' //to keep unescaped !!!! 
String newNodeName = 'twentyone' 
String parentNodeId = '20' 

String ExpectedResult = ''' 
<sample> 
    <items> 
    <one id="1">ONE</one> 
    <ten id="10">TEN</ten> 
    <twenty id="20"> 
     <twentyone>twenty&one</twentyone> 
    </twenty> 
    </items> 
</sample> 
''' 

Этот вид узлов будет содержать данные, которые будут обработаны (не для отображения HTML-страниц), так что если он спасся обработка сломается.

Возможно ли вставить новый узел с StreamingMarkupBuilder и mkp.yieldUnescaped , если я не знаю XML-контент?

Любое другое решение?

+4

Значение узла, такие как 'двадцать & one' не допускаются. Вы не можете иметь unescaped амперсанды в XML-документах. – mzjn

+0

И используя CDATA? – James

+0

также, почему вы хотите, чтобы он не был скрыт? просто чтобы вы его правильно прочитали? что не обрабатывает значение правильно, что вынуждает вас отменить его? точка экранированных данных заключается в том, что она правильно вернет целевую систему. –

ответ

1

Вот код для анализа XML-текста в Groovy как узел дерева.

def rootNode = new XmlParser().parseText(xmlSampleToEdit) 
def node = rootNode.items.'*'.find { node-> 
    node.name() == 'twenty' && [email protected] == '20' 
} 

Далее следует код, чтобы создать новый узел в качестве ребенка на узел с именем «двадцатку»:

def newNode = new groovy.util.Node(node, newNodeName) 
newNode.setValue(newNodeValue) 

Для сериализации XML обратно в текст, который вы можете использовать XmlNodePrinter или XmlUtil.serialize().

def xmlOutput = new StringWriter() 
def xmlNodePrinter = new XmlNodePrinter(new PrintWriter(xmlOutput)) 
xmlNodePrinter.with { 
    preserveWhitespace = true 
    expandEmptyElements = true 
    quote = "'" // Use single quote for attributes 
} 
xmlNodePrinter.print(rootNode) 
def output = xmlOutput.toString() 
println output 

Это ускользает текстовое содержание «двадцать один &», потому что в противном случае он не будет действительным документом XML. В XML Specification указано, что «символ амперсанда (&) и левый угловой скобок (<) не должны отображаться в их литеральной форме, за исключением случаев, когда они используются в качестве разделителей разметки ... если они необходимы в другом месте, они должны быть экранированы».

<sample> 
    <items> 
    <one id='1'>ONE</one> 
    <ten id='10'>TEN</ten> 
    <twenty id='20'> 
     <twentyone>twenty&amp;one</twentyone> 
    </twenty> 
    </items> 
</sample> 

Если хочет напечатать его незаменяемым то можно просто заменить «& усилителя» на «&» при печати.

println output.replaceAll("&amp;", "&") 

Это выведет ожидаемый результат:

<sample> 
    <items> 
    <one id='1'>ONE</one> 
    <ten id='10'>TEN</ten> 
    <twenty id='20'> 
     <twentyone>twenty&one</twentyone> 
    </twenty> 
    </items> 
</sample> 

Для получения более подробной информации о обработке XML в Groovy см http://www.groovy-lang.org/processing-xml.html

Смежные вопросы