有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

JavaGroovy:如何解析xml并保留名称空间和模式

我试图使用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>

我只想添加一个与其他子节点内联的新子节点来生成输出

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

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

这导致下游出现验证问题

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

注意:我们处理许多消息,我不知道最外层的名称空间(在上面的示例中是s1),但即使这样,我还是在寻找一种处理xml的“更愚蠢”的技术

谢谢


共 (2) 个答案

  1. # 1 楼答案

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

    此外,我还参考了这个question成功地将一个带名称空间的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 }
     )
    
  2. # 2 楼答案

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

    XmlSlurper (boolean validating, boolean namespaceAware)
    

    错:

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

    在没有将namespaceAware设置为false的情况下,我还面临解析器的奇怪行为。设置为false后,XML保持原样,不更改名称空间