In Java, how can I evaluate an XPATH expression in XML using SAX Parser?

In Java, how do I evaluate an XPATH expression in XML using SAX Parser?

A more dynamic way is required because the XML format is not fixed. So I can go through the following

  • xpath as string
  • xml as string / input source

Something like Utility.evaluate ("/ test / @ id = '123'", "")

+3


source to share


4 answers


Here's an example:

//First create a Document
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document doc = db.parse(new File("test.xml"));

//Init the xpath factory
XPath xPath =  XPathFactory.newInstance().newXPath();
String expression = "/company/employee";

//read a nodelist using xpath
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET);

      


EDIT:



If you want to use SAX parser then you cannot use XPath Java object see https://docs.oracle.com/javase/7/docs/api/javax/xml/xpath/package-summary.html

XPath provides a simple and concise syntax for selecting nodes from an XML document. XPath also provides rules for converting a node in an XML Document Object Model (DOM) tree to a boolean, double, or string value. XPath is a W3C-defined language and an official recommendation from the W3C; The W3C is hosting the XML Path Language (XPath) version 1.0 specification.

XPath began in 1999 as a complement to the XSLT and XPointer languages, but has recently become popular as a stand-alone language because a single XPath expression can be used to replace many lines of DOM API code.

If you want to use SAX, you can look at the libraries detailed in this question: Is there any XPath processor for the SAX model? ...

Although the XPath mechanic doesn't really fit SAX. Indeed, using a SAX parser will not create an in-memory XML tree. Hence, you cannot use XPath efficiently because it will not see unloaded nodes.

0


source


Only a small subset of XPath lends itself to streaming evaluations — that is, evaluating on the fly when parsing an input document. Therefore, there is not much XPath stream processor; most of them are the product of academic research projects.

One thing you might try is the SXX-EE being broadcast by XQuery. This is a small subset of XQuery that allows for streaming (this will allow expressions like your example). Details in



http://www.saxonica.com/documentation/#!sourcedocs/streaming/streamed-query

0


source


Oracle XQuery Processor for Java will "dynamically" stream expressions: https://docs.oracle.com/database/121/ADXDK/adx_j_xqj.htm#ADXDK99930

Specifically, there is information about streaming here, including an example: https://docs.oracle.com/database/121/ADXDK/adx_j_xqj.htm#ADXDK119

But it won't be a SAX stream. You must bind the input XML as StAX, InputStream or Reader to get the streaming score.

0


source


You can use SAXSource

with XPath using Saxon, but - and this is important - keep in mind that the base implementation will almost certainly load and buffer some or all of the document in memory to estimate the xpath.It probably won't be a complete DOM tree (Saxon relies to its own structure called TinyTree

one that supports lazy loading and various other optimizations), so it's better than using most DOM implementations, but still involves loading the document into memory. If your problem is memory overhead for large datasets, this probably won't help you, and you'd be better off using one of the streampath xpath / xquery options suggested by others.

Your utility method implementation might look something like this:

import java.io.StringReader;

import javax.xml.namespace.QName;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;

import org.xml.sax.InputSource;

import net.sf.saxon.xpath.XPathFactoryImpl;

public class XPathUtils {

    public static Object evaluate(String xpath, String xml, QName returnType)
            throws Exception {
        SAXParser parser = (SAXParser) SAXParserFactory.newInstance()
                .newSAXParser();
        InputSource source = new InputSource(new StringReader(xml));
        SAXSource saxSource = new SAXSource(parser.getXMLReader(), source);
        XPath xPath = new XPathFactoryImpl().newXPath();
        return xPath.evaluate(xpath, saxSource, returnType);
    }

    public static String xpathString(String xpath, String xml)
            throws Exception {
        return (String) evaluate(xpath, xml, XPathConstants.STRING);
    }

    public static boolean xpathBool(String xpath, String xml) throws Exception {
        return (Boolean) evaluate(xpath, xml, XPathConstants.BOOLEAN);
    }

    public static Number xpathNumber(String xpath, String xml) throws Exception {
        return (Number) evaluate(xpath, xml, XPathConstants.NUMBER);
    }

    public static void main(String[] args) throws Exception {
        System.out.println(xpathString("/root/@id", "<root id='12345'/>"));
    }
}

      

This works because the Saxon implementation XPath

maintains SAXSource

both the context for evaluate()

. Be aware that trying to accomplish this with the built-in Apaache implementation XPath

will throw an exception.

0


source







All Articles