5 Using Advanced XML APIs
This chapter includes the following section:
Using the WebLogic XPath API
The WebLogic XPath API contains all of the classes required to perform XPath matching against a document represented as a DOM, an XMLInputStream, or an XMLOutputStream. Use the API if you want to identify a subset of XML elements within an XML document that conform to a given pattern.
For additional API reference information about the WebLogic XPath API, see weblogic.xml.xpath in the Java API Reference for Oracle WebLogic Server.
Using the DOMXPath Class
This section describes how to use the DOMXPath class of the WebLogic XPath API to perform XPath matching against an XML document represented as a DOM. The section first provides an example and then a description of the main steps used in the example.
Example of Using the DOMXPath Class
The sample Java program at the end of this section uses the following XML document in its matching:
<?xml version='1.0' encoding='us-ascii'?>
<!-- "Purchaseorder". -->
<purchaseorder
department="Sales"
date="01-11-2001"
raisedby="Pikachu"
>
<item
ID="101">
<title>Laptop</title>
<quantity>5</quantity>
<make>Dell</make>
</item>
<item
ID="102">
<title>Desktop</title>
<quantity>15</quantity>
<make>Dell</make>
</item>
<item
ID="103">
<title>Office Software</title>
<quantity>10</quantity>
<make>Microsoft</make>
</item>
</purchaseorder>
The Java code example is as follows:
package examples.xml.xpath; import java.io.IOException; import java.util.Iterator; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.SAXException; import weblogic.xml.xpath.DOMXPath; import weblogic.xml.xpath.XPathException; /** * This class provides a simple example of how to use the DOMXPath * API. * * @author Copyright (c) 2002 by BEA Systems, Inc. */ public abstract class DOMXPathExample { public static void main(String[] ignored) throws XPathException, ParserConfigurationException, SAXException, IOException { // create a dom representation of the document String file = "purchaseorder.xml"; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); // doesn't matter for this example DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(file); // create some instances of DOMXPath to evaluate against the // document. DOMXPath totalItems = // count number of items new DOMXPath("count(purchaseorder/item)"); DOMXPath atLeast10 = // titles of items with quantity >= 10 new DOMXPath("purchaseorder/item[quantity >= 10]/title"); // evaluate them against the document double count = totalItems.evaluateAsNumber(doc); Set nodeset = atLeast10.evaluateAsNodeset(doc); // output results System.out.println(file+" contains "+count+" total items."); System.out.println("The following items have quantity >= 10:"); if (nodeset != null) { Iterator i = nodeset.iterator(); while(i.hasNext()) { Node node = (Node)i.next(); System.out.println(" "+node.getNodeName()+ ": "+node.getFirstChild().getNodeValue()); } } // note that at this point we are free to continue using evaluate // atLeast10 and totalItems against other documents } }
When adapting this controlled local-file example to untrusted XML, use the following alternative parser setup:
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
String file = "purchaseorder.xml";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
Document doc;
try (InputStream in = Files.newInputStream(Path.of(file))) {
doc = factory.newDocumentBuilder().parse(in);
}
// Continue with the existing DOMXPath declarations and evaluations against doc.A controlled workflow requiring a trusted DTD or schema should use an allowlisting resolver or catalog instead of removing the restrictions wholesale.
Main Steps When Using the DOMXPath Class
The following procedure describes the main steps to use the DOMXPath class to perform XPath matching against an XML document represented as a DOM:
For additional API reference information about the WebLogic XPath API, see weblogic.xml.xpath in the Java API Reference for Oracle WebLogic Server.
Using the StreamXPath Class
Note:
StreamXPath remains available for compatibility with applications that use weblogic.xml.stream. The underlying XMLInputStream API is deprecated in favor of standard StAX. StreamXPath implements a subset of XPath; unsupported constructs include several axes and core functions documented in the StreamXPath API reference. For new streaming designs, start with the standard StAX APIs and use this WebLogic API only when its compatibility behavior and XPath subset meet the application’s requirements.
The example in this section shows how to use the StreamXPath class of the WebLogic XPath API to perform XPath matching against an XMLInputStream. The section first provides an example and then a description of the main steps used in the example. Although the example shows how to match only against an XMLInputStream, you can use similar code to match against an XMLOutputStream.
Example of Using the StreamXPath Class
StreamXPath uses deprecated stream types and a defined XPath subset. Review the compatibility guidance in Using the StreamXPath Class before using this example.
The sample Java program at the end of this section uses the following XML document in its matching:
<?xml version='1.0' encoding='us-ascii'?>
<!-- "Stock Quotes". -->
<stock_quotes>
<stock_quote symbol='BEAS'>
<when>
<date>01/27/2001</date>
<time>3:40PM</time>
</when>
<price type="ask" value="65.1875"/>
<price type="open" value="64.00"/>
<price type="dayhigh" value="66.6875"/>
<price type="daylow" value="64.75"/>
<change>+2.1875</change>
<volume>7050200</volume>
</stock_quote>
<stock_quote symbol='MSFT'>
<when>
<date>01/27/2001</date>
<time>3:40PM</time>
</when>
<price type="ask" value="55.6875"/>
<price type="open" value="50.25"/>
<price type="dayhigh" value="56"/>
<price type="daylow" value="52.9375"/>
<change>+5.25</change>
<volume>64282200</volume>
</stock_quote>
</stock_quotes>
The Java code for the example is as follows:
package examples.xml.xpath; import java.io.File; import weblogic.xml.stream.Attribute; import weblogic.xml.stream.StartElement; import weblogic.xml.stream.XMLEvent; import weblogic.xml.stream.XMLInputStream; import weblogic.xml.stream.XMLInputStreamFactory; import weblogic.xml.stream.XMLStreamException; import weblogic.xml.xpath.StreamXPath; import weblogic.xml.xpath.XPathException; import weblogic.xml.xpath.XPathStreamFactory; import weblogic.xml.xpath.XPathStreamObserver; /** * This class provides a simple example of how to use the StreamXPath * API. * * @author Copyright (c) 2002 by BEA Systems, Inc. */ public abstract class StreamXPathExample { public static void main(String[] ignored) throws XPathException, XMLStreamException { // Create instances of StreamXPath for two xpaths we want to match // against this stream. StreamXPath symbols = new StreamXPath("stock_quotes/stock_quote"); StreamXPath openingPrices = new StreamXPath("stock_quotes/stock_quote/price[@type='open']"); // Create an XPathStreamFactory. XPathStreamFactory factory = new XPathStreamFactory(); // Create and install two XPathStreamObservers. In this case, we // just use two anonymous classes to print a message when a // callback is received. Note that a given observer can observe // more than one xpath, and a given xpath can be observed by // multiple observers. factory.install(symbols, new XPathStreamObserver () { public void observe(XMLEvent event) { System.out.println("Matched a quote: "+event); } public void observeAttribute(StartElement e, Attribute a) {} //ignore public void observeNamespace(StartElement e, Attribute a) {} //ignore }); // Note that we get matches for both a start and an end elements, // even in the case of <price/> which is an empty element - this // is the behavior of the underlying streaming parser. factory.install(openingPrices, new XPathStreamObserver () { public void observe(XMLEvent event) { System.out.println("Matched an opening price: "+event); } public void observeAttribute(StartElement e, Attribute a) {} //ignore public void observeNamespace(StartElement e, Attribute a) {} //ignore }); // get an XMLInputStream on the document String file = "stocks.xml"; XMLInputStream sourceStream = XMLInputStreamFactory.newInstance(). newInputStream(new File(file)); // use the factory to create an XMLInputStream that will do xpath // matching against the source stream XMLInputStream matchingStream = factory.createStream(sourceStream); // now iterate through the stream System.out.println("Matching against xml stream from "+file); while(matchingStream.hasNext()) { // we don't do anything with the events in our example - the // XPathStreamObserver instances that we installed in the // factory will get callbacks for appropriate events XMLEvent event = matchingStream.next(); } } }
Main Steps When Using the StreamXPath Class
StreamXPath uses deprecated stream types and a defined XPath subset. Review the compatibility guidance in Using the StreamXPath Class before using this example.
The following procedure describes the main steps to use the StreamXPath class to perform XPath matching against an XML document represented as an XMLInputStream:
For additional API reference information about the WebLogic XPath API, see weblogic.xml.xpath in the Java API Reference for Oracle WebLogic Server.