I have following xml file:
<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>
This code was created using Groovy MarkupBuilder.
Now I would like to parse this file in a groovy script:
def xml = new XmlParser().parseText(getDocXmlAsString());
xml.nodes.node.each {
Map spec = it.@spec; // here I got an exception org.codehaus.groovy.r开发者_StackOverflow社区untime.typehandling.GroovyCastException
}
but I keep getting this exception:
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'
My question, how to parse an xml attribute which is a map?
I suspect the code and xml you posted are not the actual code and xml you are having troubles with...
However, assuming you meant to close the <node/> tags when posting your example xml, I tried this Groovy code:
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
}
And it works, and prints out:
{spec_a=0.9, spec_b=0.1}
{spec_a=0.1, spec_b=0.3}
{}
These are Strings, not Maps as you seem to want...
To get them as Maps, you could do:
xml.nodes.node.each {
spec = Eval.me( it.@spec.tr( '{=}', '[:]' ) )
println spec
}
You need the tr call, to convert the format you have chosen for your maps into a format groovy can handle...
As you say you generate the XML, can I suggest you change your xml to:
<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>
As then, you can skip the tr() step...or use Json or something other than your bespoke format?
Not sure storing a map in an attribute is a good way forward...it feels a little bit brittle to me :-/
EDIT
I see what you mean, it is the Groovy MarkupBuilder adding that strange formating when it adds an attribute as a Map...
Maybe one solution would be to do something like this?
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
}
That would output:
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]
As you can see, each map entry is added as an attribute, and these can be extracted back out using the attributes() call on each Node class from the XmlParser
加载中,请稍侯......
精彩评论