>XPath 2.0 Evaluation with PsychoPath

>This post is a follow up to an earlier post on using the PsychoPath XPath 2.0 processor for validation of XPath 2.0 expressions. PsychoPath is a Java 1.5 based processor that is fully XML Schema Aware. In this entry, I’ll show how to use the processor portion of PsychoPath to evaluate an xpath expression. I’ll be using the Junit test framework for the examples.

The XML Input:

The xml input that the xpath expression we’ll be evaluating comes from the W3C XQuery test suite.


<employees>
<employee>
<location>Boston</location>
<salary>60000</salary>
<deptno>1</deptno>
</employee>
<employee>
<location>Denver</location>
<salary>60000</salary>
<deptno>1</deptno>
</employee>
<employee>
<location>Denver</location>
<salary>70000</salary>
<deptno>1</deptno>
</employee>
<employee>
<location>Denver</location>
<salary>80000</salary>
<deptno>2</deptno>
</employee>
<employee>
<location>Boston</location>
<salary>70000</salary>
<deptno>1</deptno>
</employee>
</employees>

The XPath string we will be using is just a very basic XPath string that works either in XPath 1.0 or XPath 2.0:

/employees/employee[1]/location

This string when executed should return us the the location node in the first employee element. It should contain the text value “Boston”.

Loading the XML:

Psychopath works directly off a DOM Document. In fact it also is designed to work with the Xerces XML processor and leverages it for the XML Schema aware abilities within the processor.


protected void setUp() throws Exception {
super.setUp();
Bundle bundle = Platform.getBundle("org.eclipse.wst.xml.xpath2.processor.tests");
URL fileURL = bundle.getEntry("/TestSources/acme_corp.xml");
InputStream is = fileURL.openStream();
DOMLoader domloader = new XercesLoader();
domloader.set_validating(false);
domDoc = domloader.load(is);
}

The above will load the XML from the folder in the eclipse plugin specificed. PsychoPath actually does not depend on eclipse, the test case here is setup to run though as an eclipse Junit Plugin, thus we need to tell it where in the bundle the file resides. It uses Xerces to load and create the DOM Document and store it into the domDoc field.

Setting up the Processor for Evaluation:

The processor needs to be setup with some initial information in order to parse and process the xpath expression. This is done through some helper utility methods used within the test.



private XSModel getGrammar() {
ElementPSVI rootPSVI = (ElementPSVI)domDoc.getDocumentElement();
XSModel schema = rootPSVI.getSchemaInformation();
return schema;
}

private DynamicContext setupDynamicContext(XSModel schema) {
DynamicContext dc = new DefaultDynamicContext(schema, domDoc);
dc.add_namespace("xsd", "http://www.w3.org/2001/XMLSchema");
dc.add_namespace("xdt", "http://www.w3.org/2004/10/xpath-datatypes");

dc.add_function_library(new FnFunctionLibrary());
dc.add_function_library(new XSCtrLibrary());
dc.add_function_library(new XDTCtrLibrary());
return dc;
}

private XPath compileXPath(DynamicContext dc, String xpath)
throws XPathParserException, StaticError {
XPathParser xpp = new JFlexCupParser();
XPath path = xpp.parse(xpath);

StaticChecker name_check = new StaticNameResolver(dc);
name_check.check(path);
return path;
}

PsychoPath uses the StaticChecker to help resolve function names and other user defined functions that may have been contributed. The DynamicContext holds the various function libraries that the processor knows about as well as the data types.

Evaluating an XPath Expression:

The final step is to put it all together and process the xpath based on the information from the DOM Document loaded earlier.



public void testProcessSimpleXpath() throws Exception {
// Get XML Schema Information for the Document
XSModel schema = getGrammar();

DynamicContext dc = setupDynamicContext(schema);

String xpath = "/employees/employee[1]/location";

XPath path = compileXPath(dc, xpath);

Evaluator eval = new DefaultEvaluator(dc, domDoc);
ResultSequence rs = eval.evaluate(path);

ElementType result = (ElementType)rs.first();
String resultValue = result.node_value().getTextContent();

assertEquals("Unexpected value returned", "Boston", resultValue);
}

When this test runs, it should return “Boston” as the resultValue. If it does not then the expression fails. In this case it does work, and we get the expected value. In xpath 2.0, everything is returned as a Sequence, so evaluation will always return a ResultSequence. ResultSequence does have a size() method which will contain the number of sequences returned.

PsychoPath’s result set records are typed as per the specification, so the value will be one of the supported Data types. The default is to be AnyType. The user interface API for the processor is very straight forward, and is fairly simple to use. It could be used to help an XML Schema implementation add full support for the XML Schema 1.1 assertions. Similar to how Michael Kay has enabled full XPath 2.0 assertions in Saxon-SA.

Advertisements
This entry was posted in eclipse, xml, xpath, xslt. Bookmark the permalink.

2 Responses to >XPath 2.0 Evaluation with PsychoPath

  1. Laurent M says:

    >Hey DavidThanks for this great postMay I raise an issue here ?My question is:So the processor return a ResultSequence.How can we convert an element from the sequence to a implementation of Element (such as org.dom4j.Element for Dom4j)

  2. David Carver says:

    >LaurentM: A ResultSequence methods returns an AnyType object. You can use an instanceOf check to see if it’s a NodeType, and then the value() method on there can return you a org.w3c.Element.You should be able to implement your own DefaultSequence method, and appropriate factor for returning other items, and NodeTypes. Or you can extend AnyType so that it returns the appropriate type for your particular framework. The default instance works with the W3C DOM.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s