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
相关产品推荐
相关产品推荐

