Groovy:GPath - 读取一个节点属性是映射的xml文件

时间:2010-10-06 14:24:45

标签: groovy casting map xml-parsing

我有以下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创建的。

现在我想用一个groovy脚本解析这个文件:

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 :(得分:0)

我怀疑你发布的代码和xml不是真正的代码和xml你遇到麻烦......

但是,假设您打算在发布示例xml时关闭<node/>标记,我尝试了这个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在添加一个属性作为Map时添加了奇怪的格式...

也许有一种解决方案可以做这样的事情吗?

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调用来提取这些条目>