使用Groovy向现有的XML文档添加一个XML节点

5
我使用Groovy,试图将一个使用XmlSlurper解析的xml节点插入到xml文档中。我成功在文档末尾添加了节点,但无法插入到我实际需要的位置。
原始文档:
<xml-fragment xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config"> 
    <ser:coreEntry isProxy="true" isEnabled="true" isTracingEnabled="false">
        <ser:binding type="SOAP" isSoap12="false" xsi:type="con:SoapBindingType" xmlns:con="http://www.bea.com/wli/sb/services/bindings/config">
          <con:wsdl ref="bus/src/main/osb/interfaces/apilink/ChargeServices"/>
          <con:port>
            <con:name>ChargeServicesPort</con:name>
            <con:namespace>java:dk.tdc.apilink.logic.sessions.interfaces</con:namespace>
          </con:port>
          <con:selector type="SOAP body"/>
        </ser:binding>
    </ser:coreEntry>
</xml-fragment>

要添加的片段
def fragmentToAddXml = '''
<ser:security xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config">hello</ser:security>
'''

这是我正在使用的代码。
def root = new XmlSlurper().parseText(file.getText())

root.'core-entry'.appendNode( fragmentToAddXml )
def xmlBuilder = new groovy.xml.StreamingMarkupBuilder().bind{ mkp.yield root }

请注意,新节点应该被放置在“ser:binding”节点之前
结果应该是:
<xml-fragment xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config"> 
        <ser:coreEntry isProxy="true" isEnabled="true" isTracingEnabled="false">
            <ser:security xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config">hello</ser:security>

            <ser:binding type="SOAP" isSoap12="false" xsi:type="con:SoapBindingType" xmlns:con="http://www.bea.com/wli/sb/services/bindings/config">
              <con:wsdl ref="bus/src/main/osb/interfaces/apilink/ChargeServices"/>
              <con:port>
                <con:name>ChargeServicesPort</con:name>
                <con:namespace>java:dk.tdc.apilink.logic.sessions.interfaces</con:namespace>
              </con:port>
              <con:selector type="SOAP body"/>
            </ser:binding>
        </ser:coreEntry>
    </xml-fragment>

感谢您,Luciano。
1个回答

11

给定一个XML字符串(用于测试)

def xml = '''<xml-fragment xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config"> 
    <ser:coreEntry isProxy="true" isEnabled="true" isTracingEnabled="false">
        <ser:binding type="SOAP" isSoap12="false" xsi:type="con:SoapBindingType" xmlns:con="http://www.bea.com/wli/sb/services/bindings/config">
          <con:wsdl ref="bus/src/main/osb/interfaces/apilink/ChargeServices"/>
          <con:port>
            <con:name>ChargeServicesPort</con:name>
            <con:namespace>java:dk.tdc.apilink.logic.sessions.interfaces</con:namespace>
          </con:port>
          <con:selector type="SOAP body"/>
        </ser:binding>
    </ser:coreEntry>
</xml-fragment>'''

你想要添加的 XML 内容如下:

def toadd = '''<ser:security xmlns:ser="http://www.bea.com/wli/sb/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:con="http://www.bea.com/wli/sb/pipeline/config">
  hello
</ser:security>'''

然后您可以解析它们(使用XmlSlurper并将第二个true参数设置为使用命名空间)

def root = new XmlSlurper( false, true ).parseText( xml )
fragmentToAdd = new XmlSlurper( false, true ).parseText( toadd )

将XML追加到data节点中(因为您想将其放在data内,而不是lastname内)。


root.coreEntry.appendNode( fragmentToAdd )

然后将它打印出来:

String outxml = groovy.xml.XmlUtil.serialize( root )
println outxml

输出是什么:

<?xml version="1.0" encoding="UTF-8"?>
<xml-fragment>
  <ser:coreEntry xmlns:ser="http://www.bea.com/wli/sb/services" isTracingEnabled="false" isProxy="true" isEnabled="true">
    <ser:binding xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" isSoap12="false" xsi:type="SOAP">
      <con:wsdl xmlns:con="http://www.bea.com/wli/sb/services/bindings/config" ref="bus/src/main/osb/interfaces/apilink/ChargeServices"/>
      <con:port xmlns:con="http://www.bea.com/wli/sb/services/bindings/config">
        <con:name>ChargeServicesPort</con:name>
        <con:namespace>java:dk.tdc.apilink.logic.sessions.interfaces</con:namespace>
      </con:port>
      <con:selector xmlns:con="http://www.bea.com/wli/sb/services/bindings/config" type="SOAP body"/>
    </ser:binding>
    <ser:security>
    hello
  </ser:security>
  </ser:coreEntry>
</xml-fragment>

我认为这是正确的(格式不是我想要的,但是正确的);-)

编辑

如果顺序很重要,可以像这样使用 XmlParser:

def root = new XmlParser( false, true ).parseText( xml )
fragmentToAdd = new XmlParser( false, true ).parseText( toadd )

// Insert this new node at position 0 in the children of the first coreEntry node
root.find { it.name() == 'ser:coreEntry' }.children().add( 0, fragmentToAdd )

String outxml = groovy.xml.XmlUtil.serialize( root )
println outxml

1
@LucianoFiandesio 如果您将示例代码粘贴到Groovy控制台中,它是否有效?如果是这样,请更新您的问题,以显示一个更准确的XML片段,无法工作,我可以尝试让它工作 :-) - tim_yates
是的,你的代码示例完美运行,我会更新问题。 - Luciano Fiandesio
@LucianoFiandesio 只需要一个简单的 XML 失败示例即可 :-) - tim_yates
@LucianoFiandesio 已更新答案以符合问题... 祈祷好运。 - tim_yates
这段代码对我没起作用: [致命错误] :2:4: 元素的内容必须由格式良好的字符数据或标记组成。 错误:'元素的内容必须由格式良好的字符数据或标记组成。' 捕获: groovy.lang.GroovyRuntimeException: org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 4; 元素的内容必须由格式良好的字符数据或标记组成。 - jack cardozo
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接