6

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

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

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

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

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

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

但是,当我这样做时,将删除应用于根节点的名称空间和 schemaLocations。和命名空间,但不是模式位置被添加到每个子节点。

这导致下游的验证问题。

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

注意:我们处理许多消息,我不会事先知道最外层的命名空间(上例中的 s1),但即便如此,我真的只是在寻找一种对 xml 进行“愚蠢”处理的技术

谢谢!

4

2 回答 2

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 }
 )
于 2013-03-01T22:57:52.090 回答
1

如果您设置构造函数的第二个参数,则 XMLSlurper(或 XMLParser)不处理命名空间:

XmlSlurper (boolean validating, boolean namespaceAware)

为假:

def root = new XmlSlurper(false, false).parseText( sourceXML )

如果没有将 namespaceAware 设置为 false,我还面临解析器的奇怪行为。设置为 false 后,它将保持 XML 不变,不更改名称空间。

于 2016-08-25T17:19:08.487 回答