You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Groovy中使用XPath获取XML完整orderLine节点的问题求助

Groovy XPath查询XML节点的问题解决

收到的XML请求

<orderMessageRequest>
    <wave>wave01</wave>
    <orderLine>
        <orderLineNumber>1</orderLineNumber>
        <dn>123</dn>
        <productId>TestProduct1</productId>
        <attributeValue>
            <name>lotCode</name>
            <value>123</value>
            <name>lotCode1</name>
            <value>1234</value>
        </attributeValue>
    </orderLine>
    <orderLine>
        <orderLineNumber>2</orderLineNumber>
        <dn>4032455365</dn>
        <productId>TestProduct2</productId>
    </orderLine>
</orderMessageRequest>

遇到的问题

  • 使用[0]或[1]索引时,始终仅返回第一个orderLine节点
  • 查询返回的是节点文本值,而非完整的XML节点内容

现有代码

String processXml( String xml, String xpathQuery ) {
  def xpath = XPathFactory.newInstance().newXPath()
  def builder     = DocumentBuilderFactory.newInstance().newDocumentBuilder()
  def inputStream = new ByteArrayInputStream( xml.bytes )
  def records     = builder.parse(inputStream).documentElement
  def x=xpath.evaluate( xpathQuery, records );
return x;

def x=processXml( testxml, '//orderTuPickConfirmationMessageRequest/orderLine[1]/node()' )

期望结果

根据索引返回对应完整的orderLine节点,例如orderLine[1]应返回:

<orderLine>
        <orderLineNumber>1</orderLineNumber>
        <dn>123</dn>
        <productId>TestProduct1</productId>
        <attributeValue>
            <name>lotCode</name>
            <value>123</value>
            <name>lotCode1</name>
            <value>1234</value>
        </attributeValue>
    </orderLine>

问题原因及修复方案

1. 索引与节点名错误

  • XPath索引规则:XPath采用1-based索引,[1]对应第一个节点,[2]对应第二个节点,[0]不会匹配任何节点,原代码中用[0]属于无效索引。
  • 节点名笔误:调用代码中的XPath表达式使用了orderTuPickConfirmationMessageRequest,但XML根节点实际是orderMessageRequest,路径不匹配导致查询结果异常。

2. 返回值类型错误

原代码使用xpath.evaluate()的默认调用方式,默认返回节点的文本内容而非DOM节点对象。需要指定返回类型为XPathConstants.NODE获取节点,再将节点转换为XML字符串。

修复后的完整代码

import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import javax.xml.xpath.XPathConstants
import java.io.StringWriter

String processXml(String xml, String xpathQuery) {
    def xpath = XPathFactory.newInstance().newXPath()
    def builderFactory = DocumentBuilderFactory.newInstance()
    // 关闭命名空间感知(无命名空间XML需开启)
    builderFactory.setNamespaceAware(false)
    def builder = builderFactory.newDocumentBuilder()
    def inputStream = new ByteArrayInputStream(xml.bytes)
    def doc = builder.parse(inputStream)
    
    // 评估XPath,获取DOM节点
    def node = xpath.evaluate(xpathQuery, doc, XPathConstants.NODE)
    if (!node) {
        return ""
    }
    
    // 将DOM节点转换为格式化XML字符串
    def transformer = TransformerFactory.newInstance().newTransformer()
    transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes")
    transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4")
    def writer = new StringWriter()
    transformer.transform(new DOMSource(node), new StreamResult(writer))
    
    return writer.toString()
}

// 测试XML内容
def testxml = '''<orderMessageRequest>
    <wave>wave01</wave>
    <orderLine>
        <orderLineNumber>1</orderLineNumber>
        <dn>123</dn>
        <productId>TestProduct1</productId>
        <attributeValue>
            <name>lotCode</name>
            <value>123</value>
            <name>lotCode1</name>
            <value>1234</value>
        </attributeValue>
    </orderLine>
    <orderLine>
        <orderLineNumber>2</orderLineNumber>
        <dn>4032455365</dn>
        <productId>TestProduct2</productId>
    </orderLine>
</orderMessageRequest>'''

// 获取第一个orderLine节点
def firstLine = processXml(testxml, '//orderMessageRequest/orderLine[1]')
println(firstLine)

// 获取第二个orderLine节点
def secondLine = processXml(testxml, '//orderMessageRequest/orderLine[2]')
println(secondLine)

内容的提问来源于stack exchange,提问作者keku keku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 20:23:13