Home » xmlbeans-2.5.0-src » org.apache.xmlbeans.impl.xpath » saxon » [javadoc | source]

    1   /*   Copyright 2004 The Apache Software Foundation
    2    *
    3    *   Licensed under the Apache License, Version 2.0 (the "License");
    4    *   you may not use this file except in compliance with the License.
    5    *   You may obtain a copy of the License at
    6    *
    7    *       http://www.apache.org/licenses/LICENSE-2.0
    8    *
    9    *   Unless required by applicable law or agreed to in writing, software
   10    *   distributed under the License is distributed on an "AS IS" BASIS,
   11    *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   12    *   See the License for the specific language governing permissions and
   13    *  limitations under the License.
   14    */
   15   
   16   package org.apache.xmlbeans.impl.xpath.saxon;
   17   
   18   import java.util.List;
   19   import java.util.Map;
   20   import java.util.ListIterator;
   21   
   22   import javax.xml.transform.dom.DOMSource;
   23   import javax.xml.transform.TransformerException;
   24   
   25   import org.w3c.dom.Node;
   26   
   27   import net.sf.saxon.Configuration;
   28   import net.sf.saxon.dom.NodeWrapper;
   29   import net.sf.saxon.om.NodeInfo;
   30   import net.sf.saxon.om.VirtualNode;
   31   import net.sf.saxon.om.Item;
   32   import net.sf.saxon.value.Value;
   33   import net.sf.saxon.sxpath.XPathEvaluator;
   34   import net.sf.saxon.sxpath.XPathExpression;
   35   import net.sf.saxon.sxpath.IndependentContext;
   36   import net.sf.saxon.sxpath.XPathDynamicContext;
   37   import net.sf.saxon.sxpath.XPathVariable;
   38   
   39   import org.apache.xmlbeans.impl.store.PathDelegate;
   40   
   41   public class XBeansXPath
   42           implements PathDelegate.SelectPathInterface
   43   {
   44       private Object[] namespaceMap;
   45       private String path;
   46       private String contextVar;
   47       private String defaultNS;
   48   
   49       /**
   50        * Construct given an XPath expression string.
   51        * @param path The XPath expression
   52        * @param contextVar The name of the context variable
   53        * @param namespaceMap a map of prefix/uri bindings for NS support
   54        * @param defaultNS the uri for the default element NS, if any
   55        */
   56       public XBeansXPath(String path, String contextVar,
   57                          Map namespaceMap, String defaultNS)
   58       {
   59           this.path = path;
   60           this.contextVar = contextVar;
   61           this.defaultNS = defaultNS;
   62           this.namespaceMap = namespaceMap.entrySet().toArray();
   63       }
   64   
   65       /**
   66        * Select all nodes that are selectable by this XPath
   67        * expression. If multiple nodes match, multiple nodes
   68        * will be returned.
   69        * <p/>
   70        * <p/>
   71        * <b>NOTE:</b> In most cases, nodes will be returned
   72        * in document-order, as defined by the XML Canonicalization
   73        * specification.  The exception occurs when using XPath
   74        * expressions involving the <code>union</code> operator
   75        * (denoted with the pipe '|' character).
   76        * </p>
   77        * <p/>
   78        * <p/>
   79        * <b>NOTE:</b> Param node must be a DOM node which will be used
   80        * during the xpath execution and iteration through the results. 
   81        * A call of node.dispose() must be done after reading all results.
   82        * </p>
   83        *
   84        * @param node The node, nodeset or Context object for evaluation.
   85        * This value can be null.
   86        * @return The <code>List</code> of all items selected
   87        *         by this XPath expression.
   88        */
   89       public List selectNodes(Object node)
   90       {
   91           try
   92           {
   93               Node contextNode = (Node)node;
   94               XPathEvaluator xpe = new XPathEvaluator();
   95               Configuration config = new Configuration();
   96               config.setDOMLevel(2);
   97               config.setTreeModel(net.sf.saxon.event.Builder.STANDARD_TREE);
   98               IndependentContext sc = new IndependentContext(config);
   99               // Declare ns bindings
  100               if (defaultNS != null)
  101                   sc.setDefaultElementNamespace(defaultNS);
  102   
  103               for (int i = 0; i < namespaceMap.length; i++)
  104               {
  105                   Map.Entry entry = (Map.Entry) namespaceMap[i];
  106                   sc.declareNamespace((String) entry.getKey(),
  107                           (String) entry.getValue());
  108               }
  109               xpe.setStaticContext(sc);
  110               XPathVariable thisVar = xpe.declareVariable("", contextVar);
  111               XPathExpression xpath = xpe.createExpression(path);
  112               NodeInfo contextItem = 
  113                   //config.buildDocument(new DOMSource(contextNode));
  114                   config.unravel(new DOMSource(contextNode));
  115               XPathDynamicContext dc = xpath.createDynamicContext(null);
  116               dc.setContextItem(contextItem);
  117               dc.setVariable(thisVar, contextItem);
  118   
  119               List saxonNodes = xpath.evaluate(dc);
  120               for (ListIterator it = saxonNodes.listIterator(); it.hasNext(); )
  121               {
  122                   Object o = it.next();
  123                   if (o instanceof NodeInfo)
  124                   {
  125                       if (o instanceof NodeWrapper)
  126                       {
  127                           Node n = getUnderlyingNode((NodeWrapper)o);
  128                           it.set(n);
  129                       }
  130                       else
  131                       {
  132                           it.set(((NodeInfo)o).getStringValue());
  133                       }
  134                   }
  135                   else if (o instanceof Item)
  136                       it.set(Value.convertToJava((Item)o));
  137               }
  138               return saxonNodes;
  139           }
  140           catch (TransformerException e)
  141           {
  142               throw new RuntimeException(e);
  143           }
  144       }
  145   
  146       public List selectPath(Object node)
  147       {
  148           return selectNodes(node);
  149       }
  150   
  151       /**
  152        * According to the Saxon javadoc: 
  153        * <code>getUnderlyingNode</code> in <code>NodeWrapper</code> implements 
  154        * the method specified in the interface <code>VirtualNode</code>, and
  155        * the specification of the latter says that it may return another
  156        * <code>VirtualNode</code>, and you may have to drill down through
  157        * several layers of wrapping.
  158        * To be safe, this method is provided to drill down through multiple
  159        * layers of wrapping.
  160        * @param v The <code>VirtualNode</code>
  161        * @return The underlying node
  162        */
  163       private static Node getUnderlyingNode(VirtualNode v)
  164       {
  165           Object o = v;
  166           while (o instanceof VirtualNode)
  167           {
  168               o = ((VirtualNode)o).getUnderlyingNode();
  169           }
  170           return (Node)o;
  171       }
  172   
  173   }

Home » xmlbeans-2.5.0-src » org.apache.xmlbeans.impl.xpath » saxon » [javadoc | source]