org.jdom2.contrib.xpath.xalan.XalanXPathExpression Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jdom Show documentation
Show all versions of jdom Show documentation
A complete, Java-based solution for accessing, manipulating,
and outputting XML data
The newest version!
package org.jdom2.contrib.xpath.xalan;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.transform.TransformerException;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.QName;
import org.apache.xpath.VariableStack;
import org.apache.xpath.XPath;
import org.apache.xpath.XPathContext;
import org.apache.xpath.axes.NodeSequence;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Attr;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.jdom2.Attribute;
import org.jdom2.CDATA;
import org.jdom2.Comment;
import org.jdom2.Content;
import org.jdom2.DocType;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.EntityRef;
import org.jdom2.Namespace;
import org.jdom2.NamespaceAware;
import org.jdom2.ProcessingInstruction;
import org.jdom2.Text;
import org.jdom2.contrib.dom.DOM;
import org.jdom2.contrib.dom.Wrapper;
import org.jdom2.filter.Filter;
import org.jdom2.xpath.util.AbstractXPathCompiled;
/**
* An XPathExpression that wraps the JDOM content in DOM wrappers
* and then uses the Direct Xalan API to implement XPath.
*
* @author Rolf Lear
*
* @param the type of the coerced results.
*/
class XalanXPathExpression extends AbstractXPathCompiled implements PrefixResolver {
private final XPath xpath;
private final VariableStack variables = new VariableStack() {
@Override
public XObject getVariableOrParam(XPathContext xctxt, QName qname)
throws TransformerException {
if (qname == null) {
throw new IllegalArgumentException("Null qname");
}
final Object varValue = getVariable(qname.getLocalName(),
Namespace.getNamespace(qname.getNamespaceURI()));
if ( varValue == null ) {
throw new TransformerException(
"No such variable " + qname.toNamespacedString());
}
return XObject.create(varValue, xctxt);
}
};
/**
* Construct the XPathExpression.
* @param query The XPath query to create.
* @param filter The coercion filter.
* @param variables The variable map
* @param namespaces The scope namespaces.
*/
public XalanXPathExpression(final String query, final Filter filter,
final Map variables, final Namespace[] namespaces) {
super(query, filter, variables, namespaces);
// Create an object to resolve namespace prefixes.
// XPath namespaces are resolved from the input context node's document element
// if it is a root node, or else the current context node (for lack of a better
// resolution space, given the simplicity of this sample code).
// Create the XPath object.
try {
xpath = new XPath(query, null, this, XPath.SELECT, null);
} catch (TransformerException e) {
throw new IllegalArgumentException("Unable to parse: " + query, e);
}
}
private final Node wrap(Object context) {
if (context == null) {
return DOM.wrap(new Document(), false);
}
if (context instanceof Document) {
return DOM.wrap((Document)context);
}
if (context instanceof Content) {
switch (((Content)context).getCType()) {
case CDATA:
return DOM.wrap((CDATA)context);
case Comment:
return DOM.wrap((Comment)context);
case DocType:
return DOM.wrap((DocType)context);
case Element:
return DOM.wrap((Element)context);
case EntityRef:
return DOM.wrap((EntityRef)context);
case ProcessingInstruction:
return DOM.wrap((ProcessingInstruction)context);
case Text:
return DOM.wrap((Text)context);
}
}
if (context instanceof Attribute) {
return DOM.wrap((Attribute)context);
}
throw new IllegalArgumentException("Unable to wrap context: " + context);
}
@Override
protected List> evaluateRawAll(Object context) {
// Execute the XPath, and have it return the result
// return xpath.execute(xpathSupport, contextNode, prefixResolver);
final XPathContext xpathSupport = new XPathContext(false);
xpathSupport.setVarStack(variables);
final Node contextNode = wrap(context);
final int ctxtNode = xpathSupport.getDTMHandleFromNode(contextNode);
try {
final XObject xo = xpath.execute(xpathSupport, ctxtNode, this);
ArrayList