使用Groovy编辑XML字符串 [英] Editing an XML String with Groovy

查看:213
本文介绍了使用Groovy编辑XML字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


  • 我有一个包含XML数据的字符串。
  • 我需要插入一个新节点作为特定节点的子节点(我知道'id'属性)
  • 当我打印新的xml数据时,新的节点值必须未转义。
  • 代码:

     字符串xmlSampleToEdit ='''
    < sample>
    <项目>
    < one id =1> ONE< / one>
    < ten id =10> TEN< / ten>
    < twenty id =20>< / twenty>
    < / item>
    < / sample>
    '''
    String newNodeValue ='twenty& one'//保持未转义状态!
    String newNodeName ='twentyone'
    字符串parentNodeId ='20'

    字符串ExpectedResult ='''
    < sample>
    <项目>
    < one id =1> ONE< / one>
    < ten id =10> TEN< / ten>
    < twenty id =20>
    < twentyone> twenty& one< / twentyone>
    < / twenty>
    < / item>
    < / sample>
    '''

    这种节点将包含将要处理的数据(不适用于显示HTML页面),所以如果它逃脱处理将会中断。



    如果我不知道XML内容,是否可以使用StreamingMarkupBuilder和mkp.yieldUnescaped
    插入新节点?



    其他解决方案?

    解决方案

    这里是将Groovy中的XML文本解析为树的代码节点。

      def rootNode = new XmlParser()。parseText(xmlSampleToEdit)
    def node = rootNode.items。' *'。find {node->
    node.name()=='twenty'&& node。@ id =='20'
    }

    接下来是创建一个新的代码节点名为twenty的节点:

      def newNode = new groovy.util.Node(node,newNodeName)
    newNode.setValue(newNodeValue)

    要将XML序列化回文本,您可以使用 XmlNodePrinter XmlUtil.serialize()

      def xmlOutput = new StringWriter )
    def xmlNodePrinter = new XmlNodePrinter(new PrintWriter(xmlOutput))
    xmlNodePrinter.with {
    preserveWhitespace = true
    expandEmptyElements = true
    quote ='//对于属性使用单引号

    xmlNodePrinter.print(rootNode)
    def output = xmlOutput.toString()
    println输出

    这样可以避免二十一文本内容,否则它不会是有效的XML文档。 XML规范规定和号字符(&)和左尖括号(<)不得以其文字形式出现,除非用作标记分隔符......如果它们在其他地方需要,则必须转义。

     <样品> 
    <项目>
    < one id ='1'> ONE< / one>
    < ten id ='10'> TEN< / ten>
    < twenty id ='20'>
    < twentyone> 20& amp; amp; amp; amp;< / twentyone>
    < / twenty>
    < / item>
    < / sample>

    如果想要打印它,可以简单地将& amp替换为&当打印它。

      println output.replaceAll(&,&)

    这会输出预期结果:

     <样品> 
    <项目>
    < one id ='1'> ONE< / one>
    < ten id ='10'> TEN< / ten>
    < twenty id ='20'>
    < twentyone> twenty& one< / twentyone>
    < / twenty>
    < / item>
    < / sample>

    有关在Groovy中处理XML的更多详细信息,请参阅 http://www.groovy-lang.org/processing-xml.html


    • I have a string that contains XML data.
    • I need to insert a new node as child of a specific node (I know 'id' attribute of the parent)
    • The new node value must be unescaped when i print the new xml data.

    code:

    String xmlSampleToEdit = '''
    <sample>
      <items>
        <one id="1">ONE</one>
        <ten id="10">TEN</ten>
        <twenty id="20"></twenty>
      </items>
    </sample>
    '''
    String newNodeValue = 'twenty&one' //to keep unescaped !!!!
    String newNodeName = 'twentyone'
    String parentNodeId = '20'
    
    String ExpectedResult = '''
    <sample>
      <items>
        <one id="1">ONE</one>
        <ten id="10">TEN</ten>
        <twenty id="20">
           <twentyone>twenty&one</twentyone>
        </twenty>
      </items>
    </sample>
    '''
    

    This kind of nodes will contain data that will be processed (not for displaying HTML pages) so if it's escaped processing will break.

    Is it possible to insert the new node with StreamingMarkupBuilder and mkp.yieldUnescaped if I don't know the XML content ?

    Any other solution ?

    解决方案

    Here is code to parse the XML text in Groovy as a tree node.

    def rootNode = new XmlParser().parseText(xmlSampleToEdit) 
    def node = rootNode.items.'*'.find { node->
        node.name() == 'twenty' && node.@id == '20'
    }
    

    Next is code to create a new node as child to the node named "twenty":

    def newNode = new groovy.util.Node( node, newNodeName )
    newNode.setValue(newNodeValue)
    

    To serialize the XML back to text you can use XmlNodePrinter or XmlUtil.serialize().

    def xmlOutput = new StringWriter()
    def xmlNodePrinter = new XmlNodePrinter(new PrintWriter(xmlOutput))
    xmlNodePrinter.with {
        preserveWhitespace = true
        expandEmptyElements = true
        quote = "'" // Use single quote for attributes
    }
    xmlNodePrinter.print(rootNode)
    def output = xmlOutput.toString() 
    println output
    

    This escapes the "twenty&one" text content because otherwise it would not be a valid XML document. The XML Specification states that "the ampersand character (&) and the left angle bracket (<) must not appear in their literal form, except when used as markup delimiters...if they are needed elsewhere, they must be escaped".

    <sample>
      <items>
        <one id='1'>ONE</one>
        <ten id='10'>TEN</ten>
        <twenty id='20'>
          <twentyone>twenty&amp;one</twentyone>
        </twenty>
      </items>
    </sample>
    

    If want to print it unescaped then can simply replace "&amp" to "&" when printing it.

    println output.replaceAll("&amp;", "&")
    

    This would output the expected result:

    <sample>
      <items>
        <one id='1'>ONE</one>
        <ten id='10'>TEN</ten>
        <twenty id='20'>
          <twentyone>twenty&one</twentyone>
        </twenty>
      </items>
    </sample>
    

    For more details on processing XML in Groovy see http://www.groovy-lang.org/processing-xml.html

    这篇关于使用Groovy编辑XML字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆