xom-interest AT lists.ibiblio.org
Subject: XOM API for Processing XML with Java
List archive
- From: Laurent Bihanic <laurent.bihanic AT atosorigin.com>
- To: XOM-interest <XOM-interest AT lists.ibiblio.org>
- Subject: [XOM-interest] XPath support for XOM
- Date: Thu, 30 Jan 2003 16:16:20 +0100
[Same mail but with the source code attached!]
Hi,
Attached are 2 classes that add XPath support to XOM using the Jaxen path
engine (1.0 FCS). I ran quick tests including tests on XPath functions and
namespace support and so far everything seems OK.
I put these classes in a package nu.xom.xpath.jaxen thinking XOM should wrap
them into an engine-independent XPath class, the way JDOM does. Opinions?
Laurent
/*
*/
package nu.xom.xpath.jaxen;
import org.jaxen.JaxenException;
import org.jaxen.BaseXPath;
import org.jaxen.Navigator;
import org.jaxen.XPath;
/**
* An XPath implementation for the XOM model
* <p>
* This is the main entry point for matching an XPath against a XOM
* tree. You create a compiled XPath object, then match it against
* one or more context nodes using the {@link #selectNodes}
* method, as in the following example:</p>
* <pre>
* Object xomNode = ...; // Document, Element, etc.
* XPath path = new XOMXPath("a/b/c");
* List results = path.selectNodes(xomNode);
* </pre>
*
* @see <a href="http://jaxen.sourceforge.net/">The Jaxen project</a>
*/
public class XOMXPath extends BaseXPath
{
/**
* Constructs given an XPath expression string.
*
* @param xpathExpr The XPath expression.
*
* @throws JaxenException if there is a syntax error while
* parsing the expression.
*/
public XOMXPath(String xpathExpr) throws JaxenException
{
super(xpathExpr, DocumentNavigator.getInstance());
}
}
/*
*/
package nu.xom.xpath.jaxen;
import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;
import org.jaxen.XPath;
import org.jaxen.DefaultNavigator;
import org.jaxen.FunctionCallException;
import org.jaxen.util.SingleObjectIterator;
import org.saxpath.SAXPathException;
import nu.xom.Attribute;
import nu.xom.Comment;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Node;
import nu.xom.ParentNode;
import nu.xom.ProcessingInstruction;
import nu.xom.Text;
import nu.xom.Builder;
/**
* Class for navigating around the XOM object model.
* <p>
* This class is not intended for direct usage, but is used by the
* Jaxen engine during XPath expression evaluation.</p>
*/
public class DocumentNavigator extends DefaultNavigator {
/**
* Singleton implementation.
*/
private static class Singleton {
/**
* Singleton instance.
*/
private static DocumentNavigator instance = new DocumentNavigator();
}
public static DocumentNavigator getInstance() {
return Singleton.instance;
}
public boolean isElement(Object obj) {
return obj instanceof Element;
}
public boolean isComment(Object obj) {
return obj instanceof Comment;
}
public boolean isText(Object obj) {
return obj instanceof Text;
}
public boolean isAttribute(Object obj) {
return obj instanceof Attribute;
}
public boolean isProcessingInstruction(Object obj) {
return obj instanceof ProcessingInstruction;
}
public boolean isDocument(Object obj) {
return obj instanceof Document;
}
public boolean isNamespace(Object obj) {
return obj instanceof XPathNamespace;
}
public String getElementName(Object obj) {
return ((Element)obj).getLocalName();
}
public String getElementNamespaceUri(Object obj) {
String uri = ((Element)obj).getNamespaceURI();
return ((uri != null) && (uri.length() == 0))? null: uri;
}
public String getAttributeName(Object obj) {
return ((Attribute)obj).getLocalName();
}
public String getAttributeNamespaceUri(Object obj) {
String uri = ((Attribute)obj).getNamespaceURI();
return ((uri != null) && (uri.length() == 0))? null: uri;
}
public Iterator getChildAxisIterator(Object contextNode) {
if (contextNode instanceof ParentNode) {
ParentNode e = (ParentNode)contextNode;
int max = e.getChildCount();
List content = new ArrayList(max);
for (int i=0; i<max; i++) {
content.add(e.getChild(i));
}
return content.iterator();
}
return null;
}
public Iterator getNamespaceAxisIterator(Object contextNode) {
if (contextNode instanceof Element == false) {
return null;
}
Map nsMap = new HashMap();
Element context = (Element)contextNode;
Element current = context;
while (current != null) {
String uri;
String prefix;
uri = current.getNamespaceURI();
if (uri.length() != 0) {
prefix = current.getNamespacePrefix();
if (!nsMap.containsKey(prefix)) {
nsMap.put(prefix,
new XPathNamespace(context, prefix, uri));
}
}
int max = current.getNamespaceDeclarationCount();
for (int i=0; i<max; i++) {
prefix = current.getNamespacePrefix(i);
if (!nsMap.containsKey(prefix)) {
nsMap.put(prefix,
new XPathNamespace(context, prefix, uri));
}
}
ParentNode parent = current.getParent();
current = (parent instanceof Element)? (Element)parent: null;
}
nsMap.put("xml", new XPathNamespace(context,
"xml", "http://www.w3.org/XML/1998/namespace"));
return nsMap.values().iterator();
}
public Iterator getParentAxisIterator(Object contextNode) {
Object parent = null;
if (contextNode instanceof Node) {
parent = ((Node)contextNode).getParent();
}
else if (contextNode instanceof XPathNamespace) {
parent = ((XPathNamespace)contextNode).getElement();
}
if (parent != null) {
return new SingleObjectIterator(parent);
}
return null;
}
public Iterator getAttributeAxisIterator(Object contextNode) {
if (contextNode instanceof Element) {
Element e = (Element)contextNode;
int max = e.getAttributeCount();
List attrs = new ArrayList(max);
for (int i=0; i<max; i++) {
attrs.add(e.getAttribute(i));
}
return attrs.iterator();
}
return null;
}
/**
* Returns a parsed form of the given xpath string, which will
* be suitable for queries on JDOM documents.
*/
public XPath parseXPath (String xpath) throws SAXPathException {
return new XOMXPath(xpath);
}
public Object getDocumentNode(Object contextNode) {
if (contextNode instanceof Node) {
return ((Node)contextNode).getDocument();
}
return null;
}
public String getElementQName(Object obj) {
return ((Element)obj).getQualifiedName();
}
public String getAttributeQName(Object obj) {
return ((Attribute)obj).getQualifiedName();
}
public String getNamespaceStringValue(Object obj) {
return ((XPathNamespace)obj).getURI();
}
public String getNamespacePrefix(Object obj) {
return ((XPathNamespace)obj).getPrefix();
}
public String getTextStringValue(Object obj) {
if (obj instanceof Text) {
return ((Text)obj).getValue();
}
return "";
}
public String getAttributeStringValue(Object obj) {
return ((Attribute)obj).getValue();
}
public String getElementStringValue(Object obj) {
return ((Element)obj).getValue();
}
public String getProcessingInstructionTarget(Object obj) {
return ((ProcessingInstruction)obj).getTarget();
}
public String getProcessingInstructionData(Object obj) {
return ((ProcessingInstruction)obj).getValue();
}
public String getCommentStringValue(Object obj) {
return ((Comment)obj).getValue();
}
public String translateNamespacePrefixToUri(String prefix, Object context)
{
Element element = null;
if (context instanceof Element) {
element = (Element)context;
}
else if (context instanceof Node) {
Node parent = ((Node)context).getParent();
if (parent instanceof Element) {
element = (Element)context;
}
}
else if (context instanceof XPathNamespace) {
element = ((XPathNamespace)context).getElement();
}
if ( element != null ) {
String uri = element.getNamespaceURI(prefix);
if (uri.length() != 0) {
return uri;
}
}
return null;
}
public Object getDocument(String url) throws FunctionCallException {
try {
return new Builder().build(url);
}
catch (Exception e) {
throw new FunctionCallException(e.getMessage());
}
}
private static class XPathNamespace {
/** * The XOM element to which the namespace is attached. */
private Element element;
/** * The namespace prefix. */
private String prefix;
/** * The namespace URI. */
private String uri;
/**
* Creates a namespace-node wrapper for a namespace node
* assigned to the given element.
*/
public XPathNamespace(Element element, String prefix, String uri)
{
this.element = element;
this.prefix = prefix;
this.uri = uri;
}
/**
* Returns the element from which this namespace node has
* been retrieved. The result may be null when the namespace
* node has not yet been assigned to an element.
*
* @return the element from which this namespace node has
* been retrieved.
*/
public Element getElement()
{
return this.element;
}
/**
* Returns the namespace prefix of this namespace node.
*
* @return the namespace prefix of this namespace node.
*/
public String getPrefix()
{
return this.prefix;
}
/**
* Returns the namespace URI of this namespace node.
*
* @return the namespace URI of this namespace node.
*/
public String getURI()
{
return this.uri;
}
public String toString()
{
return ("[xmlns:" + this.getPrefix() + "=\"" +
this.getURI() + "\", element=" +
this.getElement().getLocalName() + "]" );
}
}
}
-
[XOM-interest] XPath support for XOM,
Laurent Bihanic, 01/30/2003
- Re: [XOM-interest] XPath support for XOM, Elliotte Rusty Harold, 01/30/2003
- <Possible follow-up(s)>
- [XOM-interest] XPath support for XOM, Laurent Bihanic, 01/30/2003
Archive powered by MHonArc 2.6.24.