6

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

ただし、これを行うと、ルート ノードに適用される名前空間と schemaLocations が削除されます。スキーマの場所ではなく名前空間が各子ノードに追加されています。

これにより、下流で検証の問題が発生しています。

このxmlを単純に処理するにはどうすればよいですか。検証を実行せず、xml をそのままにして、指定した名前空間の単一ノードを追加しますか?

1 つの注意: 私たちは多くのメッセージを処理しており、最も外側の名前空間 (上記の例では s1) を事前に知ることはできませんが、それでも、xml の「愚かな」処理である手法を探しているだけです。

ありがとう!

4

2 に答える 2

3

まず、xsi 名前空間を定義するために xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" を追加する必要がありました。これがないと、バインドされていない 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

コンストラクターの 2 番目のパラメーターを設定すると、XMLSlurper (または XMLParser) は名前空間を処理しません。

XmlSlurper (boolean validating, boolean namespaceAware)

false に:

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

namespaceAware を false に設定しないと、パーサーの奇妙な動作にも直面しました。false に設定すると、名前空間は変更されず、XML はそのままになります。

于 2016-08-25T17:19:08.487 に答える