代码之家  ›  专栏  ›  技术社区  ›  Skarab

groovy:gpath-读取节点属性为映射的XML文件

  •  1
  • Skarab  · 技术社区  · 14 年前

    我有以下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 回复  |  直到 14 年前
        1
  •  0
  •   tim_yates    14 年前

    我怀疑您发布的代码和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