Groovy:如何解析xml并保留名称空间和schemaLocations

Bet*_*033 6 java groovy

我正在尝试使用groovy来简单地将节点添加到特定位置.我的源架构看起来像这样

<s1:RootNode
   xmlns:s1="http://localhost/s1schema"
   xmlns:s2="http://localhost/s2schema"
   xsi:schemaLocation="http://localhost/s1schema s1schema.xsd 
   http://localhost/s2schema s2schema.xsd">
 <s1:aParentNode>
  <s2:targetNode>
   <s2:childnode1 />
   <s2:childnode2 />
   <s2:childnode3 />
   <s2:childnode4 />
 </s2:targetNode>
</s1:aParentNode>
</s1:RootNode>
Run Code Online (Sandbox Code Playgroud)

我想简单地添加一个与其他子节点内联的新子节点来进行输出

<s1:RootNode
    xmlns:s1="http://localhost/s1schema"
    xmlns:s2="http://localhost/s2schema"
    xsi:schemaLocation="http://localhost/s1schema s1schema.xsd 
    http://localhost/s2schema s2schema.xsd">
 <s1:aParentNode>    
   <s2:targetNode>
     <s2:childnode1 />
     <s2:childnode2 />
     <s2:childnode3 />
     <s2:childnode4 />
     <s2:childnode5 >value</s2:childnode5>
   </s2:targetNode>
  </s1:aParentNode>
 </s1:RootNode>
Run Code Online (Sandbox Code Playgroud)

为此,我有以下简单的groovy脚本

  def data = 'value'
def root = new XmlSlurper(false,true).parseText( sourceXML )
        root.'aParentNode'.'topNode'.appendNode{
            's2:childnode5' data
        }
groovy.xml.XmlUtil.serialize(root);
Run Code Online (Sandbox Code Playgroud)

但是,当我这样做时,将删除应用于根节点的名称空间和schemaLocations.和命名空间,但没有将架构位置添加到每个子节点.

这导致下游的验证问题.

我如何简单地处理这个xml.不执行验证并按原样保留xml并添加我指定的命名空间的单个节点?

一个注意事项:我们处理了很多消息,我不会事先知道最外面的命名空间(上例中的s1),但即便如此,我真的只是想看一种技术,它是xml的"笨"处理

谢谢!

pur*_*101 3

首先,我必须添加 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 来定义您的 xsi 命名空间。如果没有它,我将收到未绑定 xsi 前缀的 SAXParseException。

此外,我咨询了有关成功将命名空间 xml 节点添加到现有文档的问题。

最后,我们必须利用 StreamingMarkupBuilder 来解决命名空间的移动问题。基本上,默认情况下,序列化器将引用的命名空间移动到实际使用该命名空间的第一个节点。在您的情况下,它将您的 s2 命名空间属性移动到“targetNode”标签。以下代码生成您想要的结果,但您仍然必须知道用于实例化 StreamingMarkupBuilder 的正确命名空间。

 def root = new XmlSlurper(false, true).parseText( sourceXML )
 def data = '<s2:childnode5 xmlns:s2="http://localhost/s2schema">value</s2:childnode5>'
 def xmlFragment = new XmlSlurper(false, true).parseText(data)
 root.'aParentNode'.'targetNode'.appendNode(xmlFragment);

 def outputBuilder = new StreamingMarkupBuilder()
 String result = XmlUtil.serialize(outputBuilder.bind {
     mkp.declareNamespace('s1':"http://localhost/s1schema")
     mkp.declareNamespace('s2':"http://localhost/s2schema")
     mkp.yield root }
 )
Run Code Online (Sandbox Code Playgroud)