Groovy: GPath - чтение XML-файла, в котором атрибутом узла является карта - PullRequest
1 голос
/ 06 октября 2010

У меня есть следующий XML-файл:

<doc_xml>
<nodes>
  <node id='1' spec="{spec_a=0.9, spec_b=0.1}" />
  <node id='2' spec="{spec_a=0.1, spec_b=0.3}" />
  <node id='3' spec="{}" />
</nodes>
</doc_xml>

Этот код был создан с использованием Groovy MarkupBuilder.

Теперь я хотел бы проанализировать этот файл в отличном сценарии:

def xml = new XmlParser().parseText(getDocXmlAsString());

xml.nodes.node.each {
   Map spec = it.@spec; // here I got an exception org.codehaus.groovy.runtime.typehandling.GroovyCastException

}

но я продолжаю получать это исключение:

org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object '{spec_a=0.9, spec_b=0.1}' with class 'java.lang.String' to class 'java.util.Map'

Мой вопрос, как разобрать атрибут xml, который является картой?

1 Ответ

0 голосов
/ 06 октября 2010

Я подозреваю, что код и отправленные вами xml не являются действительными кодами и xml, с которыми у вас возникают проблемы ...

Однако, если вы намеревались закрыть теги <node/> при публикации примера xml,Я попробовал этот код Groovy:

def xmlStr = """<doc_xml>
<nodes>
  <node id='1' spec="{spec_a=0.9, spec_b=0.1}"/>
  <node id='2' spec="{spec_a=0.1, spec_b=0.3}"/>
  <node id='3' spec="{}"/>
</nodes>
</doc_xml>"""

def xml = new XmlParser().parseText( xmlStr )
def spec = [:]

xml.nodes.node.each {
  spec = it.@spec
  println spec
}

И это работает, и распечатывает:

{spec_a=0.9, spec_b=0.1}
{spec_a=0.1, spec_b=0.3}
{}

Это строки, а не карты, как вы, кажется, хотите ...

Чтобы получить их как Карты, вы можете сделать:

xml.nodes.node.each {
  spec = Eval.me( it.@spec.tr( '{=}', '[:]' ) )
  println spec
}

Вам нужен вызов tr, чтобы преобразовать формат, выбранный для ваших карт, в формат, который может обрабатывать groovy ...

Когда вы говорите, что генерируете XML, могу ли я предложить вам изменить xml на:

<doc_xml>
<nodes>
  <node id='1' spec="[spec_a:0.9, spec_b:0.1]"/>
  <node id='2' spec="[spec_a:0.1, spec_b:0.3]"/>
  <node id='3' spec="[:]"/>
</nodes>
</doc_xml>

Как и тогда, вы можете пропустить шаг tr() ... или использовать Json или что-то другоечем ваш формат на заказ?

Не уверен, что сохранение карты в атрибуте - хороший путь вперед ... мне это кажется немного ломким: - /

РЕДАКТИРОВАТЬ

Я понимаю, что вы имеете в виду, это Groovy MarkupBuilder, добавляющий это странное форматирование, когда он добавляет атрибуткак карта ...

Может быть, одним из решений было бы сделать что-то вроде этого?

import groovy.xml.MarkupBuilder

// Imaginary data that we're going to generate our XML from:
def nodeData = [
  [ id:1, spec_a:0.9, spec_b:0.1 ],
  [ id:2, spec_a:0.1, spec_b:0.3 ],
  [ id:3 ]
]

def writer = new StringWriter()
def xml = new MarkupBuilder(writer)
xml.doc_xml() {
  nodes() {
    nodeData.each {
      node( it )
    }
  }
}

def xmlStr = writer.toString()

println "Write out the XML"
println xmlStr

def xmlParse = new XmlParser().parseText( xmlStr )
def spec = [:]

println "Write out the Attributes for each node"
xmlParse.nodes.node.each {
  spec = it.attributes()
  println spec
}

Что бы вывести:

Write out the XML
<doc_xml>
  <nodes>
    <node id='1' spec_a='0.9' spec_b='0.1' />
    <node id='2' spec_a='0.1' spec_b='0.3' />
    <node id='3' />
  </nodes>
</doc_xml>
Write out the Attributes for each node
[id:1, spec_a:0.9, spec_b:0.1]
[id:2, spec_a:0.1, spec_b:0.3]
[id:3]

Как вы можете видетькаждая запись на карте добавляется как атрибут, и их можно извлечь обратно с помощью вызова attributes() для каждого класса Node из XmlParser

...