2010-10-06 16 views
1

Je suit le fichier xml:Groovy: GPath - la lecture d'un fichier xml dans lequel un attribut node est une carte

<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> 

Ce code a été créé à l'aide Groovy MarkupBuilder.

Maintenant, je voudrais analyser ce fichier dans un script groovy:

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

xml.nodes.node.each { 
    Map spec = [email protected]; // here I got an exception org.codehaus.groovy.runtime.typehandling.GroovyCastException 

} 

mais je continue à recevoir cette 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' 

Ma question, comment analyser un attribut xml qui est carte?

Répondre

0

Je soupçonne que le code et XML ne sont pas au courant du code réel et xml que vous rencontrez des problèmes avec ...

Cependant, en supposant que vous vouliez dire de fermer les balises <node/> lors de la publication de votre exemple xml, j'ai essayé ce Code 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 = [email protected] 
    println spec 
} 

et cela fonctionne, et imprime:

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

ce sont des chaînes, pas de cartes que vous semblez vouloir ...

Pour les obtenir sous forme de cartes, vous pouvez faire:

xml.nodes.node.each { 
    spec = Eval.me([email protected]('{=}', '[:]')) 
    println spec 
} 

Vous avez besoin du tr appel, pour convertir le format que vous avez choisi pour vos cartes dans un groovy format peut gérer ...

comme vous le dites vous générez le XML, puis-je vous suggère de changer votre 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> 

comme alors, vous pouvez sauter l'étape tr() ... ou utiliser JSON ou autre chose que votre format sur mesure?

Pas sûr de stocker une carte dans un attribut est une bonne voie à suivre ... il se sent un peu fragile pour moi: -/

EDIT

Je vois ce que vous voulez dire, il est le Groovy MarkupBuilder en ajoutant cette formation étrange quand il ajoute un attribut comme une carte ...

Peut-être une solution serait de faire quelque chose comme ceci?

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 
} 

Ce serait sortie:

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] 

Comme vous pouvez le voir, chaque entrée de carte est ajoutée comme un attribut, et ceux-ci peuvent être désextraits à l'aide de l'appel attributes() sur chaque classe Node de la XmlParser

+0

Comment configurer Groovy MarkupBuilder pour produire "[:]" au lieu de "{:}"? – Skarab

+0

Je suis d'accord que le stockage de Map dans un attribut n'est pas la meilleure pratique.Mais je suis en train de créer un prototype, donc je ne veux pas dépenser beaucoup d'efforts pour écrire un analyseur pour une hiérarchie xml complexe. – Skarab

+0

Je vois ce que vous voulez dire à propos de MarkupBuilder produisant ce format de carte ... J'ai ajouté une solution possible au fond de ma réponse ... J'espère que ça aide :-) –