问题 如何在Groovy中创建XPath函数


我正在尝试在Groovy中创建一个执行以下操作的函数:

  1. 在运行时接受2个参数(一串XML和一个xpath查询)
  2. 以文本形式返回结果

这可能非常简单,但有两个障碍:

  1. 这必须在groovy中完成
  2. 我对Groovy或Java几乎一无所知......

这是我通过黑客攻击各种代码而得到的,但现在我被卡住了:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.*;

builder  = DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc      = builder.parse(new ByteArrayInputStream(xml.bytes));
expr     = XPathFactory.newInstance().newXPath().compile(expression);
Object result = expr.evaluate(doc, XPathConstants.NODESET)

其中“xml”和“expression”是运行时参数。我现在如何得到这个结果(作为字符串)?

谢谢


2966
2018-02-15 18:16


起源



答案:


你可以这样做:

import javax.xml.xpath.*
import javax.xml.parsers.DocumentBuilderFactory

def testxml = '''
    <records>
      <car name="HSV Maloo" make="Holden" year="2006">
        <country>Australia</country>
        <record type="speed">Production Pickup Truck with speed of 271kph</record>
      </car>
    </records>
  '''

def 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
  xpath.evaluate( xpathQuery, records )
}

println processXml( testxml, '//car/record/@type' )

看看这个页面(以前是Groovy Docs的一部分),了解如何循环返回多个结果的XPath查询:

http://groovy.jmiguel.eu/groovy.codehaus.org/Reading+XML+with+Groovy+and+XPath.html


14
2018-02-15 22:42



蒂姆,非常感谢你的帮助。这对我来说是一个巨大的节省时间。 - Jack James
你救了我的命 - Fueled By Coffee


答案:


你可以这样做:

import javax.xml.xpath.*
import javax.xml.parsers.DocumentBuilderFactory

def testxml = '''
    <records>
      <car name="HSV Maloo" make="Holden" year="2006">
        <country>Australia</country>
        <record type="speed">Production Pickup Truck with speed of 271kph</record>
      </car>
    </records>
  '''

def 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
  xpath.evaluate( xpathQuery, records )
}

println processXml( testxml, '//car/record/@type' )

看看这个页面(以前是Groovy Docs的一部分),了解如何循环返回多个结果的XPath查询:

http://groovy.jmiguel.eu/groovy.codehaus.org/Reading+XML+with+Groovy+and+XPath.html


14
2018-02-15 22:42



蒂姆,非常感谢你的帮助。这对我来说是一个巨大的节省时间。 - Jack James
你救了我的命 - Fueled By Coffee


这是我最终解决的问题,这应该适用于我的目的:

import javax.xml.xpath.*
import javax.xml.parsers.DocumentBuilderFactory

def 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 nodes       = xpath.evaluate( xpathQuery, records, XPathConstants.NODESET )
  nodes.collect { node -> node.textContent }

}

processXml( xml, query )

0
2018-02-16 10:13



不错的片段。出于某种原因,对于我的示例xhtml,执行似乎在builder.parse停滞不前:没有明显的CPU使用率或I / O.也许某种网络超时? - Tomislav Nakic-Alfirevic