#xml #groovy
#xml #groovy
Вопрос:
Я новичок в groovy и изо всех сил пытаюсь изменить (или скопировать) и существующий XML-файл, сжимая части, принадлежащие одному и тому же идентификатору. Это пример исходного XML:
<ROOT>
<JDE>
<ID>1</ID>
<ORDERS>
<ORDER>123</ORDER>
</ORDERS>
</JDE>
<JDE>
<ID>1</ID>
<ORDERS>
<ORDER>234</ORDER>
</ORDERS>
</JDE>
<JDE>
<ID>2</ID>
<ORDERS>
<ORDER>345</ORDER>
</ORDERS>
</JDE>
</ROOT>
As you can see, we can have several <JDE> Tags for the same person (ID). Now I need to detect those redundancies and copy all Orders to the first node of this person. The end result shall be this:
<ROOT>
<JDE>
<ID>1</ID>
<ORDERS>
<ORDER>123</ORDER>
<ORDER>234</ORDER>
</ORDERS>
</JDE>
<JDE>
<ID>2</ID>
<ORDERS>
<ORDER>345</ORDER>
</ORDERS>
</JDE>
</ROOT>
Я не понимаю, могу ли я добиться этого, изменив файл с помощью XMLParser или мне нужно создать другой файл с помощью MarkupBuilder?
Это мое кодирование до сих пор (в основном для выявления дубликатов):
def body = message.getBody(String.class) //xml file
def xmlParser = new XmlParser()
def List = xmlParser.parseText(body)
def IdList = []
Root.JDE.each{
def ID = it.ID
if ( IdList.contains(ID) )
{
//ID already found, now iterate again to find first occurence
//copy the order node and delete the JDE node of the duplicate
// --> ifI need to iterate again, can I use Root.JDE.each again?
}
else
{
//do nothing or copy node to a target xml file
IdList.add(Employee_ID)
}
}
Ответ №1:
Почти идентичный ответ, но с использованием замыкания для поиска заказов по заданному идентификатору:
import groovy.xml.MarkupBuilder
def body = '''
<ROOT>
<JDE>
<ID>1</ID>
<ORDERS>
<ORDER>123</ORDER>
</ORDERS>
</JDE>
<JDE>
<ID>1</ID>
<ORDERS>
<ORDER>234</ORDER>
</ORDERS>
</JDE>
<JDE>
<ID>2</ID>
<ORDERS>
<ORDER>345</ORDER>
</ORDERS>
</JDE>
</ROOT>
'''
def root = new XmlParser().parseText(body)
def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
ids = root.JDE.ID.collect { it.text() }.unique()
def orderById = { id ->
root.JDE.ID
.findAll { it.text() == id }
.collect { it.parent().ORDERS.ORDER.text() }
}
xml.ROOT() {
ids.each { id ->
JDE() {
ID(id)
ORDERS() {
orderById(id).each { o ->
ORDER(o)
}
}
}
}
}
println writer.toString()
Ответ №2:
Рабочий пример здесь
Вероятно, будет проще писать, тестировать и поддерживать, если мы разделим это на два этапа: создадим карту из старой структуры и используем карту для создания новой модели.
Рассмотрим:
def xmlParser = new XmlParser()
def root = xmlParser.parseText(body)
// 1. build map
def map = [:].withDefault{ key -> [] }
root.JDE.each { jde ->
def id = jde.ID.text()
jde.ORDERS.each { order ->
map[id] << order.text()
}
}
// 2. use map to build new XML structure
def writer = new StringWriter()
new groovy.xml.MarkupBuilder(writer).ROOT {
map.each { id, orderIds ->
JDE() {
ID(id)
ORDERS() {
orderIds.each { orderId ->
ORDER(orderId)
}
}
}
}
}
println writer.toString()
Комментарии:
1. Нет проблем… Пожалуйста, поддержите любые полезные ответы и «примите» (отметьте галочкой) тот, который отвечает на ваш вопрос.