/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the  "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * $Id: XPathContext.java 524809 2007-04-02 15:51:51Z zongaro $
 */
package org.apache.xpath;

import java.lang.reflect.Method;
import java.util.Stack;
import java.util.Vector;
import java.util.HashMap;
import java.util.Iterator;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;

import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xalan.res.XSLMessages;
import org.apache.xml.dtm.Axis;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMFilter;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.DTMWSFilter;
import org.apache.xml.dtm.ref.sax2dtm.SAX2RTFDTM;
import org.apache.xml.utils.IntStack;
import org.apache.xml.utils.NodeVector;
import org.apache.xml.utils.ObjectStack;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.SAXSourceLocator;
import org.apache.xml.utils.XMLString;
import org.apache.xpath.axes.SubContextList;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.DTMXRTreeFrag;
import org.apache.xpath.objects.XString;
import org.apache.xpath.res.XPATHErrorResources;

import org.xml.sax.XMLReader;

Default class for the runtime execution context for XPath.

This class extends DTMManager but does not directly implement it.

@xsl.usageadvanced
/** * Default class for the runtime execution context for XPath. * * <p>This class extends DTMManager but does not directly implement it.</p> * @xsl.usage advanced */
public class XPathContext extends DTMManager // implements ExpressionContext { IntStack m_last_pushed_rtfdtm=new IntStack();
Stack of cached "reusable" DTMs for Result Tree Fragments. This is a kluge to handle the problem of starting an RTF before the old one is complete. %REVIEW% I'm using a Vector rather than Stack so we can reuse the DTMs if the problem occurs multiple times. I'm not sure that's really a net win versus discarding the DTM and starting a new one... but the retained RTF DTM will have been tail-pruned so should be small.
/** * Stack of cached "reusable" DTMs for Result Tree Fragments. * This is a kluge to handle the problem of starting an RTF before * the old one is complete. * * %REVIEW% I'm using a Vector rather than Stack so we can reuse * the DTMs if the problem occurs multiple times. I'm not sure that's * really a net win versus discarding the DTM and starting a new one... * but the retained RTF DTM will have been tail-pruned so should be small. */
private Vector m_rtfdtm_stack=null;
Index of currently active RTF DTM in m_rtfdtm_stack
/** Index of currently active RTF DTM in m_rtfdtm_stack */
private int m_which_rtfdtm=-1;
Most recent "reusable" DTM for Global Result Tree Fragments. No stack is required since we're never going to pop these.
/** * Most recent "reusable" DTM for Global Result Tree Fragments. No stack is * required since we're never going to pop these. */
private SAX2RTFDTM m_global_rtfdtm=null;
HashMap of cached the DTMXRTreeFrag objects, which are identified by DTM IDs. The object are just wrappers for DTMs which are used in XRTreeFrag.
/** * HashMap of cached the DTMXRTreeFrag objects, which are identified by DTM IDs. * The object are just wrappers for DTMs which are used in XRTreeFrag. */
private HashMap m_DTMXRTreeFrags = null;
state of the secure processing feature.
/** * state of the secure processing feature. */
private boolean m_isSecureProcessing = false;
Though XPathContext context extends the DTMManager, it really is a proxy for this object, which is the real DTMManager.
/** * Though XPathContext context extends * the DTMManager, it really is a proxy for this object, which * is the real DTMManager. */
protected DTMManager m_dtmManager = DTMManager.newInstance( org.apache.xpath.objects.XMLStringFactoryImpl.getFactory());
Return the DTMManager object. Though XPathContext context extends the DTMManager, it really is a proxy for the real DTMManager. If a caller needs to make a lot of calls to the DTMManager, it is faster if it gets the real one from this function.
/** * Return the DTMManager object. Though XPathContext context extends * the DTMManager, it really is a proxy for the real DTMManager. If a * caller needs to make a lot of calls to the DTMManager, it is faster * if it gets the real one from this function. */
public DTMManager getDTMManager() { return m_dtmManager; }
Set the state of the secure processing feature
/** * Set the state of the secure processing feature */
public void setSecureProcessing(boolean flag) { m_isSecureProcessing = flag; }
Return the state of the secure processing feature
/** * Return the state of the secure processing feature */
public boolean isSecureProcessing() { return m_isSecureProcessing; }
Get an instance of a DTM, loaded with the content from the specified source. If the unique flag is true, a new instance will always be returned. Otherwise it is up to the DTMManager to return a new instance or an instance that it already created and may be being used by someone else. (I think more parameters will need to be added for error handling, and entity resolution).
Params:
  • source – the specification of the source object, which may be null, in which case it is assumed that node construction will take by some other means.
  • unique – true if the returned DTM must be unique, probably because it is going to be mutated.
  • wsfilter – Enables filtering of whitespace nodes, and may be null.
  • incremental – true if the construction should try and be incremental.
  • doIndexing – true if the caller considers it worth it to use indexing schemes.
Returns:a non-null DTM reference.
/** * Get an instance of a DTM, loaded with the content from the * specified source. If the unique flag is true, a new instance will * always be returned. Otherwise it is up to the DTMManager to return a * new instance or an instance that it already created and may be being used * by someone else. * (I think more parameters will need to be added for error handling, and entity * resolution). * * @param source the specification of the source object, which may be null, * in which case it is assumed that node construction will take * by some other means. * @param unique true if the returned DTM must be unique, probably because it * is going to be mutated. * @param wsfilter Enables filtering of whitespace nodes, and may be null. * @param incremental true if the construction should try and be incremental. * @param doIndexing true if the caller considers it worth it to use * indexing schemes. * * @return a non-null DTM reference. */
public DTM getDTM(javax.xml.transform.Source source, boolean unique, DTMWSFilter wsfilter, boolean incremental, boolean doIndexing) { return m_dtmManager.getDTM(source, unique, wsfilter, incremental, doIndexing); }
Get an instance of a DTM that "owns" a node handle.
Params:
  • nodeHandle – the nodeHandle.
Returns:a non-null DTM reference.
/** * Get an instance of a DTM that "owns" a node handle. * * @param nodeHandle the nodeHandle. * * @return a non-null DTM reference. */
public DTM getDTM(int nodeHandle) { return m_dtmManager.getDTM(nodeHandle); }
Given a W3C DOM node, try and return a DTM handle. Note: calling this may be non-optimal.
Params:
  • node – Non-null reference to a DOM node.
Returns:a valid DTM handle.
/** * Given a W3C DOM node, try and return a DTM handle. * Note: calling this may be non-optimal. * * @param node Non-null reference to a DOM node. * * @return a valid DTM handle. */
public int getDTMHandleFromNode(org.w3c.dom.Node node) { return m_dtmManager.getDTMHandleFromNode(node); } // //
%TBD% Doc
/** * %TBD% Doc */
public int getDTMIdentity(DTM dtm) { return m_dtmManager.getDTMIdentity(dtm); } //
Creates an empty DocumentFragment object.
Returns:A new DocumentFragment handle.
/** * Creates an empty <code>DocumentFragment</code> object. * @return A new <code>DocumentFragment handle</code>. */
public DTM createDocumentFragment() { return m_dtmManager.createDocumentFragment(); } //
Release a DTM either to a lru pool, or completely remove reference. DTMs without system IDs are always hard deleted. State: experimental.
Params:
  • dtm – The DTM to be released.
  • shouldHardDelete – True if the DTM should be removed no matter what.
Returns:true if the DTM was removed, false if it was put back in a lru pool.
/** * Release a DTM either to a lru pool, or completely remove reference. * DTMs without system IDs are always hard deleted. * State: experimental. * * @param dtm The DTM to be released. * @param shouldHardDelete True if the DTM should be removed no matter what. * @return true if the DTM was removed, false if it was put back in a lru pool. */
public boolean release(DTM dtm, boolean shouldHardDelete) { // %REVIEW% If it's a DTM which may contain multiple Result Tree // Fragments, we can't discard it unless we know not only that it // is empty, but that the XPathContext itself is going away. So do // _not_ accept the request. (May want to do it as part of // reset(), though.) if(m_rtfdtm_stack!=null && m_rtfdtm_stack.contains(dtm)) { return false; } return m_dtmManager.release(dtm, shouldHardDelete); }
Create a new DTMIterator based on an XPath UnionExpr.
Params:
  • xpathCompiler – ??? Somehow we need to pass in a subpart of the expression. I hate to do this with strings, since the larger expression has already been parsed.
  • pos – The position in the expression.
Returns:The newly created DTMIterator.
/** * Create a new <code>DTMIterator</code> based on an XPath * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. * * @param xpathCompiler ??? Somehow we need to pass in a subpart of the * expression. I hate to do this with strings, since the larger expression * has already been parsed. * * @param pos The position in the expression. * @return The newly created <code>DTMIterator</code>. */
public DTMIterator createDTMIterator(Object xpathCompiler, int pos) { return m_dtmManager.createDTMIterator(xpathCompiler, pos); } //
Create a new DTMIterator based on an XPath UnionExpr.
Params:
  • xpathString – Must be a valid string expressing a UnionExpr.
  • presolver – An object that can resolve prefixes to namespace URLs.
Returns:The newly created DTMIterator.
/** * Create a new <code>DTMIterator</code> based on an XPath * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. * * @param xpathString Must be a valid string expressing a * <a href="http://www.w3.org/TR/xpath#NT-LocationPath>LocationPath</a> or * a <a href="http://www.w3.org/TR/xpath#NT-UnionExpr">UnionExpr</a>. * * @param presolver An object that can resolve prefixes to namespace URLs. * * @return The newly created <code>DTMIterator</code>. */
public DTMIterator createDTMIterator(String xpathString, PrefixResolver presolver) { return m_dtmManager.createDTMIterator(xpathString, presolver); } //
Create a new DTMIterator based only on a whatToShow and a DTMFilter. The traversal semantics are defined as the descendant access.
Params:
  • whatToShow – This flag specifies which node types may appear in the logical view of the tree presented by the iterator. See the description of NodeFilter for the set of possible SHOW_ values.These flags can be combined using OR.
  • filter – The NodeFilter to be used with this TreeWalker, or null to indicate no filter.
  • entityReferenceExpansion – The value of this flag determines whether entity reference nodes are expanded.
Returns:The newly created NodeIterator.
/** * Create a new <code>DTMIterator</code> based only on a whatToShow and * a DTMFilter. The traversal semantics are defined as the descendant * access. * * @param whatToShow This flag specifies which node types may appear in * the logical view of the tree presented by the iterator. See the * description of <code>NodeFilter</code> for the set of possible * <code>SHOW_</code> values.These flags can be combined using * <code>OR</code>. * @param filter The <code>NodeFilter</code> to be used with this * <code>TreeWalker</code>, or <code>null</code> to indicate no filter. * @param entityReferenceExpansion The value of this flag determines * whether entity reference nodes are expanded. * * @return The newly created <code>NodeIterator</code>. */
public DTMIterator createDTMIterator(int whatToShow, DTMFilter filter, boolean entityReferenceExpansion) { return m_dtmManager.createDTMIterator(whatToShow, filter, entityReferenceExpansion); }
Create a new DTMIterator that holds exactly one node.
Params:
  • node – The node handle that the DTMIterator will iterate to.
Returns:The newly created DTMIterator.
/** * Create a new <code>DTMIterator</code> that holds exactly one node. * * @param node The node handle that the DTMIterator will iterate to. * * @return The newly created <code>DTMIterator</code>. */
public DTMIterator createDTMIterator(int node) { // DescendantIterator iter = new DescendantIterator(); DTMIterator iter = new org.apache.xpath.axes.OneStepIteratorForward(Axis.SELF); iter.setRoot(node, this); return iter; // return m_dtmManager.createDTMIterator(node); }
Create an XPathContext instance. This is equivalent to calling the XPathContext(boolean) constructor with the value true.
/** * Create an XPathContext instance. This is equivalent to calling * the {@link #XPathContext(boolean)} constructor with the value * <code>true</code>. */
public XPathContext() { this(true); }
Create an XPathContext instance.
Params:
  • recursiveVarContext – A boolean value indicating whether the XPath context needs to support pushing of scopes for variable resolution
/** * Create an XPathContext instance. * @param recursiveVarContext A <code>boolean</code> value indicating whether * the XPath context needs to support pushing of scopes for * variable resolution */
public XPathContext(boolean recursiveVarContext) { m_prefixResolvers.push(null); m_currentNodes.push(DTM.NULL); m_currentExpressionNodes.push(DTM.NULL); m_saxLocations.push(null); m_variableStacks = recursiveVarContext ? new VariableStack() : new VariableStack(1); }
Create an XPathContext instance. This is equivalent to calling the constructor XPathContext(Object, boolean) with the value of the second parameter set to true.
Params:
  • owner – Value that can be retrieved via the getOwnerObject() method.
See Also:
/** * Create an XPathContext instance. This is equivalent to calling the * constructor {@link #XPathContext(java.lang.Object,boolean)} with the * value of the second parameter set to <code>true</code>. * @param owner Value that can be retrieved via the getOwnerObject() method. * @see #getOwnerObject */
public XPathContext(Object owner) { this(owner, true); }
Create an XPathContext instance.
Params:
  • owner – Value that can be retrieved via the getOwnerObject() method.
  • recursiveVarContext – A boolean value indicating whether the XPath context needs to support pushing of scopes for variable resolution
See Also:
/** * Create an XPathContext instance. * @param owner Value that can be retrieved via the getOwnerObject() method. * @see #getOwnerObject * @param recursiveVarContext A <code>boolean</code> value indicating whether * the XPath context needs to support pushing of scopes for * variable resolution */
public XPathContext(Object owner, boolean recursiveVarContext) { this(recursiveVarContext); m_owner = owner; try { m_ownerGetErrorListener = m_owner.getClass().getMethod("getErrorListener", new Class[] {}); } catch (NoSuchMethodException nsme) {} }
Reset for new run.
/** * Reset for new run. */
public void reset() { releaseDTMXRTreeFrags(); // These couldn't be disposed of earlier (see comments in release()); zap them now. if(m_rtfdtm_stack!=null) for (java.util.Enumeration e = m_rtfdtm_stack.elements() ; e.hasMoreElements() ;) m_dtmManager.release((DTM)e.nextElement(), true); m_rtfdtm_stack=null; // drop our references too m_which_rtfdtm=-1; if(m_global_rtfdtm!=null) m_dtmManager.release(m_global_rtfdtm,true); m_global_rtfdtm=null; m_dtmManager = DTMManager.newInstance( org.apache.xpath.objects.XMLStringFactoryImpl.getFactory()); m_saxLocations.removeAllElements(); m_axesIteratorStack.removeAllElements(); m_contextNodeLists.removeAllElements(); m_currentExpressionNodes.removeAllElements(); m_currentNodes.removeAllElements(); m_iteratorRoots.RemoveAllNoClear(); m_predicatePos.removeAllElements(); m_predicateRoots.RemoveAllNoClear(); m_prefixResolvers.removeAllElements(); m_prefixResolvers.push(null); m_currentNodes.push(DTM.NULL); m_currentExpressionNodes.push(DTM.NULL); m_saxLocations.push(null); }
The current stylesheet locator.
/** The current stylesheet locator. */
ObjectStack m_saxLocations = new ObjectStack(RECURSIONLIMIT);
Set the current locater in the stylesheet.
Params:
  • location – The location within the stylesheet.
/** * Set the current locater in the stylesheet. * * @param location The location within the stylesheet. */
public void setSAXLocator(SourceLocator location) { m_saxLocations.setTop(location); }
Set the current locater in the stylesheet.
Params:
  • location – The location within the stylesheet.
/** * Set the current locater in the stylesheet. * * @param location The location within the stylesheet. */
public void pushSAXLocator(SourceLocator location) { m_saxLocations.push(location); }
Push a slot on the locations stack so that setSAXLocator can be repeatedly called.
/** * Push a slot on the locations stack so that setSAXLocator can be * repeatedly called. * */
public void pushSAXLocatorNull() { m_saxLocations.push(null); }
Pop the current locater.
/** * Pop the current locater. */
public void popSAXLocator() { m_saxLocations.pop(); }
Get the current locater in the stylesheet.
Returns:The location within the stylesheet, or null if not known.
/** * Get the current locater in the stylesheet. * * @return The location within the stylesheet, or null if not known. */
public SourceLocator getSAXLocator() { return (SourceLocator) m_saxLocations.peek(); }
The owner context of this XPathContext. In the case of XSLT, this will be a Transformer object.
/** The owner context of this XPathContext. In the case of XSLT, this will be a * Transformer object. */
private Object m_owner;
The owner context of this XPathContext. In the case of XSLT, this will be a Transformer object.
/** The owner context of this XPathContext. In the case of XSLT, this will be a * Transformer object. */
private Method m_ownerGetErrorListener;
Get the "owner" context of this context, which should be, in the case of XSLT, the Transformer object. This is needed so that XSLT functions can get the Transformer.
Returns:The owner object passed into the constructor, or null.
/** * Get the "owner" context of this context, which should be, * in the case of XSLT, the Transformer object. This is needed * so that XSLT functions can get the Transformer. * @return The owner object passed into the constructor, or null. */
public Object getOwnerObject() { return m_owner; } // ================ VarStack ===================
The stack of Variable stacks. A VariableStack will be pushed onto this stack for each template invocation.
/** * The stack of Variable stacks. A VariableStack will be * pushed onto this stack for each template invocation. */
private VariableStack m_variableStacks;
Get the variable stack, which is in charge of variables and parameters.
Returns:the variable stack, which should not be null.
/** * Get the variable stack, which is in charge of variables and * parameters. * * @return the variable stack, which should not be null. */
public final VariableStack getVarStack() { return m_variableStacks; }
Get the variable stack, which is in charge of variables and parameters.
Params:
  • varStack – non-null reference to the variable stack.
/** * Get the variable stack, which is in charge of variables and * parameters. * * @param varStack non-null reference to the variable stack. */
public final void setVarStack(VariableStack varStack) { m_variableStacks = varStack; } // ================ SourceTreeManager ===================
The source tree manager, which associates Source objects to source tree nodes.
/** The source tree manager, which associates Source objects to source * tree nodes. */
private SourceTreeManager m_sourceTreeManager = new SourceTreeManager();
Get the SourceTreeManager associated with this execution context.
Returns:the SourceTreeManager associated with this execution context.
/** * Get the SourceTreeManager associated with this execution context. * * @return the SourceTreeManager associated with this execution context. */
public final SourceTreeManager getSourceTreeManager() { return m_sourceTreeManager; }
Set the SourceTreeManager associated with this execution context.
Params:
  • mgr – the SourceTreeManager to be associated with this execution context.
/** * Set the SourceTreeManager associated with this execution context. * * @param mgr the SourceTreeManager to be associated with this * execution context. */
public void setSourceTreeManager(SourceTreeManager mgr) { m_sourceTreeManager = mgr; } // =================================================
The ErrorListener where errors and warnings are to be reported.
/** The ErrorListener where errors and warnings are to be reported. */
private ErrorListener m_errorListener;
A default ErrorListener in case our m_errorListener was not specified and our owner either does not have an ErrorListener or has a null one.
/** A default ErrorListener in case our m_errorListener was not specified and our * owner either does not have an ErrorListener or has a null one. */
private ErrorListener m_defaultErrorListener;
Get the ErrorListener where errors and warnings are to be reported.
Returns:A non-null ErrorListener reference.
/** * Get the ErrorListener where errors and warnings are to be reported. * * @return A non-null ErrorListener reference. */
public final ErrorListener getErrorListener() { if (null != m_errorListener) return m_errorListener; ErrorListener retval = null; try { if (null != m_ownerGetErrorListener) retval = (ErrorListener) m_ownerGetErrorListener.invoke(m_owner, new Object[] {}); } catch (Exception e) {} if (null == retval) { if (null == m_defaultErrorListener) m_defaultErrorListener = new org.apache.xml.utils.DefaultErrorHandler(); retval = m_defaultErrorListener; } return retval; }
Set the ErrorListener where errors and warnings are to be reported.
Params:
  • listener – A non-null ErrorListener reference.
/** * Set the ErrorListener where errors and warnings are to be reported. * * @param listener A non-null ErrorListener reference. */
public void setErrorListener(ErrorListener listener) throws IllegalArgumentException { if (listener == null) throw new IllegalArgumentException(XSLMessages.createXPATHMessage(XPATHErrorResources.ER_NULL_ERROR_HANDLER, null)); //"Null error handler"); m_errorListener = listener; } // =================================================
The TrAX URI Resolver for resolving URIs from the document(...) function to source tree nodes.
/** The TrAX URI Resolver for resolving URIs from the document(...) * function to source tree nodes. */
private URIResolver m_uriResolver;
Get the URIResolver associated with this execution context.
Returns:a URI resolver, which may be null.
/** * Get the URIResolver associated with this execution context. * * @return a URI resolver, which may be null. */
public final URIResolver getURIResolver() { return m_uriResolver; }
Set the URIResolver associated with this execution context.
Params:
  • resolver – the URIResolver to be associated with this execution context, may be null to clear an already set resolver.
/** * Set the URIResolver associated with this execution context. * * @param resolver the URIResolver to be associated with this * execution context, may be null to clear an already set resolver. */
public void setURIResolver(URIResolver resolver) { m_uriResolver = resolver; } // =================================================
The reader of the primary source tree.
/** The reader of the primary source tree. */
public XMLReader m_primaryReader;
Get primary XMLReader associated with this execution context.
Returns:The reader of the primary source tree.
/** * Get primary XMLReader associated with this execution context. * * @return The reader of the primary source tree. */
public final XMLReader getPrimaryReader() { return m_primaryReader; }
Set primary XMLReader associated with this execution context.
Params:
  • reader – The reader of the primary source tree.
/** * Set primary XMLReader associated with this execution context. * * @param reader The reader of the primary source tree. */
public void setPrimaryReader(XMLReader reader) { m_primaryReader = reader; } // ================================================= /** Misnamed string manager for XPath messages. */ // private static XSLMessages m_XSLMessages = new XSLMessages();
Tell the user of an assertion error, and probably throw an exception.
Params:
  • b – If false, a TransformerException will be thrown.
  • msg – The assertion message, which should be informative.
Throws:
/** * Tell the user of an assertion error, and probably throw an * exception. * * @param b If false, a TransformerException will be thrown. * @param msg The assertion message, which should be informative. * * @throws javax.xml.transform.TransformerException if b is false. */
private void assertion(boolean b, String msg) throws javax.xml.transform.TransformerException { if (!b) { ErrorListener errorHandler = getErrorListener(); if (errorHandler != null) { errorHandler.fatalError( new TransformerException( XSLMessages.createMessage( XPATHErrorResources.ER_INCORRECT_PROGRAMMER_ASSERTION, new Object[]{ msg }), (SAXSourceLocator)this.getSAXLocator())); } } } //========================================================== // SECTION: Execution context state tracking //==========================================================
The current context node list.
/** * The current context node list. */
private Stack m_contextNodeLists = new Stack(); public Stack getContextNodeListsStack() { return m_contextNodeLists; } public void setContextNodeListsStack(Stack s) { m_contextNodeLists = s; }
Get the current context node list.
Returns: the current node list, also refered to here as a context node list.
/** * Get the current context node list. * * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, * also refered to here as a <term>context node list</term>. */
public final DTMIterator getContextNodeList() { if (m_contextNodeLists.size() > 0) return (DTMIterator) m_contextNodeLists.peek(); else return null; }
Set the current context node list.
Params:
@xsl.usageinternal
/** * Set the current context node list. * * @param nl the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>, * also refered to here as a <term>context node list</term>. * @xsl.usage internal */
public final void pushContextNodeList(DTMIterator nl) { m_contextNodeLists.push(nl); }
Pop the current context node list.
@xsl.usageinternal
/** * Pop the current context node list. * @xsl.usage internal */
public final void popContextNodeList() { if(m_contextNodeLists.isEmpty()) System.err.println("Warning: popContextNodeList when stack is empty!"); else m_contextNodeLists.pop(); }
The ammount to use for stacks that record information during the recursive execution.
/** * The ammount to use for stacks that record information during the * recursive execution. */
public static final int RECURSIONLIMIT = (1024*4);
The stack of current node objects. Not to be confused with the current node list. %REVIEW% Note that there are no bounds check and resize for this stack, so if it is blown, it's all over.
/** The stack of <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a> objects. * Not to be confused with the current node list. %REVIEW% Note that there * are no bounds check and resize for this stack, so if it is blown, it's all * over. */
private IntStack m_currentNodes = new IntStack(RECURSIONLIMIT); // private NodeVector m_currentNodes = new NodeVector(); public IntStack getCurrentNodeStack() {return m_currentNodes; } public void setCurrentNodeStack(IntStack nv) { m_currentNodes = nv; }
Get the current context node.
Returns:the current node.
/** * Get the current context node. * * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. */
public final int getCurrentNode() { return m_currentNodes.peek(); }
Set the current context node and expression node.
Params:
  • cn – the current node.
  • en – the sub-expression context node.
/** * Set the current context node and expression node. * * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. * @param en the sub-expression context node. */
public final void pushCurrentNodeAndExpression(int cn, int en) { m_currentNodes.push(cn); m_currentExpressionNodes.push(cn); }
Set the current context node.
/** * Set the current context node. */
public final void popCurrentNodeAndExpression() { m_currentNodes.quickPop(1); m_currentExpressionNodes.quickPop(1); }
Push the current context node, expression node, and prefix resolver.
Params:
  • cn – the current node.
  • en – the sub-expression context node.
  • nc – the namespace context (prefix resolver.
/** * Push the current context node, expression node, and prefix resolver. * * @param cn the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. * @param en the sub-expression context node. * @param nc the namespace context (prefix resolver. */
public final void pushExpressionState(int cn, int en, PrefixResolver nc) { m_currentNodes.push(cn); m_currentExpressionNodes.push(cn); m_prefixResolvers.push(nc); }
Pop the current context node, expression node, and prefix resolver.
/** * Pop the current context node, expression node, and prefix resolver. */
public final void popExpressionState() { m_currentNodes.quickPop(1); m_currentExpressionNodes.quickPop(1); m_prefixResolvers.pop(); }
Set the current context node.
Params:
/** * Set the current context node. * * @param n the <a href="http://www.w3.org/TR/xslt#dt-current-node">current node</a>. */
public final void pushCurrentNode(int n) { m_currentNodes.push(n); }
Pop the current context node.
/** * Pop the current context node. */
public final void popCurrentNode() { m_currentNodes.quickPop(1); }
Set the current predicate root.
/** * Set the current predicate root. */
public final void pushPredicateRoot(int n) { m_predicateRoots.push(n); }
Pop the current predicate root.
/** * Pop the current predicate root. */
public final void popPredicateRoot() { m_predicateRoots.popQuick(); }
Get the current predicate root.
/** * Get the current predicate root. */
public final int getPredicateRoot() { return m_predicateRoots.peepOrNull(); }
Set the current location path iterator root.
/** * Set the current location path iterator root. */
public final void pushIteratorRoot(int n) { m_iteratorRoots.push(n); }
Pop the current location path iterator root.
/** * Pop the current location path iterator root. */
public final void popIteratorRoot() { m_iteratorRoots.popQuick(); }
Get the current location path iterator root.
/** * Get the current location path iterator root. */
public final int getIteratorRoot() { return m_iteratorRoots.peepOrNull(); }
A stack of the current sub-expression nodes.
/** A stack of the current sub-expression nodes. */
private NodeVector m_iteratorRoots = new NodeVector();
A stack of the current sub-expression nodes.
/** A stack of the current sub-expression nodes. */
private NodeVector m_predicateRoots = new NodeVector();
A stack of the current sub-expression nodes.
/** A stack of the current sub-expression nodes. */
private IntStack m_currentExpressionNodes = new IntStack(RECURSIONLIMIT); public IntStack getCurrentExpressionNodeStack() { return m_currentExpressionNodes; } public void setCurrentExpressionNodeStack(IntStack nv) { m_currentExpressionNodes = nv; } private IntStack m_predicatePos = new IntStack(); public final int getPredicatePos() { return m_predicatePos.peek(); } public final void pushPredicatePos(int n) { m_predicatePos.push(n); } public final void popPredicatePos() { m_predicatePos.pop(); }
Get the current node that is the expression's context (i.e. for current() support).
Returns:The current sub-expression node.
/** * Get the current node that is the expression's context (i.e. for current() support). * * @return The current sub-expression node. */
public final int getCurrentExpressionNode() { return m_currentExpressionNodes.peek(); }
Set the current node that is the expression's context (i.e. for current() support).
Params:
  • n – The sub-expression node to be current.
/** * Set the current node that is the expression's context (i.e. for current() support). * * @param n The sub-expression node to be current. */
public final void pushCurrentExpressionNode(int n) { m_currentExpressionNodes.push(n); }
Pop the current node that is the expression's context (i.e. for current() support).
/** * Pop the current node that is the expression's context * (i.e. for current() support). */
public final void popCurrentExpressionNode() { m_currentExpressionNodes.quickPop(1); } private ObjectStack m_prefixResolvers = new ObjectStack(RECURSIONLIMIT);
Get the current namespace context for the xpath.
Returns:the current prefix resolver for resolving prefixes to namespace URLs.
/** * Get the current namespace context for the xpath. * * @return the current prefix resolver for resolving prefixes to * namespace URLs. */
public final PrefixResolver getNamespaceContext() { return (PrefixResolver) m_prefixResolvers.peek(); }
Get the current namespace context for the xpath.
Params:
  • pr – the prefix resolver to be used for resolving prefixes to namespace URLs.
/** * Get the current namespace context for the xpath. * * @param pr the prefix resolver to be used for resolving prefixes to * namespace URLs. */
public final void setNamespaceContext(PrefixResolver pr) { m_prefixResolvers.setTop(pr); }
Push a current namespace context for the xpath.
Params:
  • pr – the prefix resolver to be used for resolving prefixes to namespace URLs.
/** * Push a current namespace context for the xpath. * * @param pr the prefix resolver to be used for resolving prefixes to * namespace URLs. */
public final void pushNamespaceContext(PrefixResolver pr) { m_prefixResolvers.push(pr); }
Just increment the namespace contest stack, so that setNamespaceContext can be used on the slot.
/** * Just increment the namespace contest stack, so that setNamespaceContext * can be used on the slot. */
public final void pushNamespaceContextNull() { m_prefixResolvers.push(null); }
Pop the current namespace context for the xpath.
/** * Pop the current namespace context for the xpath. */
public final void popNamespaceContext() { m_prefixResolvers.pop(); } //========================================================== // SECTION: Current TreeWalker contexts (for internal use) //==========================================================
Stack of AxesIterators.
/** * Stack of AxesIterators. */
private Stack m_axesIteratorStack = new Stack(); public Stack getAxesIteratorStackStacks() { return m_axesIteratorStack; } public void setAxesIteratorStackStacks(Stack s) { m_axesIteratorStack = s; }
Push a TreeWalker on the stack.
Params:
  • iter – A sub-context AxesWalker.
@xsl.usageinternal
/** * Push a TreeWalker on the stack. * * @param iter A sub-context AxesWalker. * @xsl.usage internal */
public final void pushSubContextList(SubContextList iter) { m_axesIteratorStack.push(iter); }
Pop the last pushed axes iterator.
@xsl.usageinternal
/** * Pop the last pushed axes iterator. * @xsl.usage internal */
public final void popSubContextList() { m_axesIteratorStack.pop(); }
Get the current axes iterator, or return null if none.
Returns:the sub-context node list.
@xsl.usageinternal
/** * Get the current axes iterator, or return null if none. * * @return the sub-context node list. * @xsl.usage internal */
public SubContextList getSubContextList() { return m_axesIteratorStack.isEmpty() ? null : (SubContextList) m_axesIteratorStack.peek(); }
Get the current node list as defined by the XSLT spec.
Returns:the current node list.
@xsl.usageinternal
/** * Get the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a> * as defined by the XSLT spec. * * @return the <a href="http://www.w3.org/TR/xslt#dt-current-node-list">current node list</a>. * @xsl.usage internal */
public org.apache.xpath.axes.SubContextList getCurrentNodeList() { return m_axesIteratorStack.isEmpty() ? null : (SubContextList) m_axesIteratorStack.elementAt(0); } //========================================================== // SECTION: Implementation of ExpressionContext interface //==========================================================
Get the current context node.
Returns:The current context node.
/** * Get the current context node. * @return The current context node. */
public final int getContextNode() { return this.getCurrentNode(); }
Get the current context node list.
Returns:An iterator for the current context list, as defined in XSLT.
/** * Get the current context node list. * @return An iterator for the current context list, as * defined in XSLT. */
public final DTMIterator getContextNodes() { try { DTMIterator cnl = getContextNodeList(); if (null != cnl) return cnl.cloneWithReset(); else return null; // for now... this might ought to be an empty iterator. } catch (CloneNotSupportedException cnse) { return null; // error reporting? } } XPathExpressionContext expressionContext = new XPathExpressionContext();
The the expression context for extensions for this context.
Returns:An object that implements the ExpressionContext.
/** * The the expression context for extensions for this context. * * @return An object that implements the ExpressionContext. */
public ExpressionContext getExpressionContext() { return expressionContext; } public class XPathExpressionContext implements ExpressionContext {
Return the XPathContext associated with this XPathExpressionContext. Extensions should use this judiciously and only when special processing requirements cannot be met another way. Consider requesting an enhancement to the ExpressionContext interface to avoid having to call this method.
Returns:the XPathContext associated with this XPathExpressionContext.
/** * Return the XPathContext associated with this XPathExpressionContext. * Extensions should use this judiciously and only when special processing * requirements cannot be met another way. Consider requesting an enhancement * to the ExpressionContext interface to avoid having to call this method. * @return the XPathContext associated with this XPathExpressionContext. */
public XPathContext getXPathContext() { return XPathContext.this; }
Return the DTMManager object. Though XPathContext context extends the DTMManager, it really is a proxy for the real DTMManager. If a caller needs to make a lot of calls to the DTMManager, it is faster if it gets the real one from this function.
/** * Return the DTMManager object. Though XPathContext context extends * the DTMManager, it really is a proxy for the real DTMManager. If a * caller needs to make a lot of calls to the DTMManager, it is faster * if it gets the real one from this function. */
public DTMManager getDTMManager() { return m_dtmManager; }
Get the current context node.
Returns:The current context node.
/** * Get the current context node. * @return The current context node. */
public org.w3c.dom.Node getContextNode() { int context = getCurrentNode(); return getDTM(context).getNode(context); }
Get the current context node list.
Returns:An iterator for the current context list, as defined in XSLT.
/** * Get the current context node list. * @return An iterator for the current context list, as * defined in XSLT. */
public org.w3c.dom.traversal.NodeIterator getContextNodes() { return new org.apache.xml.dtm.ref.DTMNodeIterator(getContextNodeList()); }
Get the error listener.
Returns:The registered error listener.
/** * Get the error listener. * @return The registered error listener. */
public ErrorListener getErrorListener() { return XPathContext.this.getErrorListener(); }
Get the value of a node as a number.
Params:
  • n – Node to be converted to a number. May be null.
Returns:value of n as a number.
/** * Get the value of a node as a number. * @param n Node to be converted to a number. May be null. * @return value of n as a number. */
public double toNumber(org.w3c.dom.Node n) { // %REVIEW% You can't get much uglier than this... int nodeHandle = getDTMHandleFromNode(n); DTM dtm = getDTM(nodeHandle); XString xobj = (XString)dtm.getStringValue(nodeHandle); return xobj.num(); }
Get the value of a node as a string.
Params:
  • n – Node to be converted to a string. May be null.
Returns:value of n as a string, or an empty string if n is null.
/** * Get the value of a node as a string. * @param n Node to be converted to a string. May be null. * @return value of n as a string, or an empty string if n is null. */
public String toString(org.w3c.dom.Node n) { // %REVIEW% You can't get much uglier than this... int nodeHandle = getDTMHandleFromNode(n); DTM dtm = getDTM(nodeHandle); XMLString strVal = dtm.getStringValue(nodeHandle); return strVal.toString(); }
Get a variable based on it's qualified name.
Params:
  • qname – The qualified name of the variable.
Throws:
Returns:The evaluated value of the variable.
/** * Get a variable based on it's qualified name. * @param qname The qualified name of the variable. * @return The evaluated value of the variable. * @throws javax.xml.transform.TransformerException */
public final XObject getVariableOrParam(org.apache.xml.utils.QName qname) throws javax.xml.transform.TransformerException { return m_variableStacks.getVariableOrParam(XPathContext.this, qname); } }
Get a DTM to be used as a container for a global Result Tree Fragment. This will always be an instance of (derived from? equivalent to?) SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX output to it. It may be a single DTM containing for multiple fragments, if the implementation supports that. Note: The distinction between this method and getRTFDTM() is that the latter allocates space from the dynamic variable stack (m_rtfdtm_stack), which may be pruned away again as the templates which defined those variables are exited. Global variables may be bound late (see XUnresolvedVariable), and never want to be discarded, hence we need to allocate them separately and don't actually need a stack to track them.
Returns:a non-null DTM reference.
/** * Get a DTM to be used as a container for a global Result Tree * Fragment. This will always be an instance of (derived from? equivalent to?) * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX * output to it. It may be a single DTM containing for multiple fragments, * if the implementation supports that. * * Note: The distinction between this method and getRTFDTM() is that the latter * allocates space from the dynamic variable stack (m_rtfdtm_stack), which may * be pruned away again as the templates which defined those variables are exited. * Global variables may be bound late (see XUnresolvedVariable), and never want to * be discarded, hence we need to allocate them separately and don't actually need * a stack to track them. * * @return a non-null DTM reference. */
public DTM getGlobalRTFDTM() { // We probably should _NOT_ be applying whitespace filtering at this stage! // // Some magic has been applied in DTMManagerDefault to recognize this set of options // and generate an instance of DTM which can contain multiple documents // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but // I didn't want to change the manager API at this time, or expose // too many dependencies on its internals. (Ideally, I'd like to move // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly // specify the subclass here.) // If it doesn't exist, or if the one already existing is in the middle of // being constructed, we need to obtain a new DTM to write into. I'm not sure // the latter will ever arise, but I'd rather be just a bit paranoid.. if( m_global_rtfdtm==null || m_global_rtfdtm.isTreeIncomplete() ) { m_global_rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); } return m_global_rtfdtm; }
Get a DTM to be used as a container for a dynamic Result Tree Fragment. This will always be an instance of (derived from? equivalent to?) SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX output to it. It may be a single DTM containing for multiple fragments, if the implementation supports that.
Returns:a non-null DTM reference.
/** * Get a DTM to be used as a container for a dynamic Result Tree * Fragment. This will always be an instance of (derived from? equivalent to?) * SAX2DTM, since each RTF is constructed by temporarily redirecting our SAX * output to it. It may be a single DTM containing for multiple fragments, * if the implementation supports that. * * @return a non-null DTM reference. */
public DTM getRTFDTM() { SAX2RTFDTM rtfdtm; // We probably should _NOT_ be applying whitespace filtering at this stage! // // Some magic has been applied in DTMManagerDefault to recognize this set of options // and generate an instance of DTM which can contain multiple documents // (SAX2RTFDTM). Perhaps not the optimal way of achieving that result, but // I didn't want to change the manager API at this time, or expose // too many dependencies on its internals. (Ideally, I'd like to move // isTreeIncomplete all the way up to DTM, so we wouldn't need to explicitly // specify the subclass here.) if(m_rtfdtm_stack==null) { m_rtfdtm_stack=new Vector(); rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); m_rtfdtm_stack.addElement(rtfdtm); ++m_which_rtfdtm; } else if(m_which_rtfdtm<0) { rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm); } else { rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); // It might already be under construction -- the classic example would be // an xsl:variable which uses xsl:call-template as part of its value. To // handle this recursion, we have to start a new RTF DTM, pushing the old // one onto a stack so we can return to it. This is not as uncommon a case // as we might wish, unfortunately, as some folks insist on coding XSLT // as if it were a procedural language... if(rtfdtm.isTreeIncomplete()) { if(++m_which_rtfdtm < m_rtfdtm_stack.size()) rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm); else { rtfdtm=(SAX2RTFDTM)m_dtmManager.getDTM(null,true,null,false,false); m_rtfdtm_stack.addElement(rtfdtm); } } } return rtfdtm; }
Push the RTFDTM's context mark, to allows discarding RTFs added after this point. (If it doesn't exist we don't push, since we might still be able to get away with not creating it. That requires that excessive pops be harmless.)
/** Push the RTFDTM's context mark, to allows discarding RTFs added after this * point. (If it doesn't exist we don't push, since we might still be able to * get away with not creating it. That requires that excessive pops be harmless.) * */
public void pushRTFContext() { m_last_pushed_rtfdtm.push(m_which_rtfdtm); if(null!=m_rtfdtm_stack) ((SAX2RTFDTM)(getRTFDTM())).pushRewindMark(); }
Pop the RTFDTM's context mark. This discards any RTFs added after the last mark was set. If there is no RTF DTM, there's nothing to pop so this becomes a no-op. If pushes were issued before this was called, we count on the fact that popRewindMark is defined such that overpopping just resets to empty. Complicating factor: We need to handle the case of popping back to a previous RTF DTM, if one of the weird produce-an-RTF-to-build-an-RTF cases arose. Basically: If pop says this DTM is now empty, then return to the previous if one exists, in whatever state we left it in. UGLY, but hopefully the situation which forces us to consider this will arise exceedingly rarely.
/** Pop the RTFDTM's context mark. This discards any RTFs added after the last * mark was set. * * If there is no RTF DTM, there's nothing to pop so this * becomes a no-op. If pushes were issued before this was called, we count on * the fact that popRewindMark is defined such that overpopping just resets * to empty. * * Complicating factor: We need to handle the case of popping back to a previous * RTF DTM, if one of the weird produce-an-RTF-to-build-an-RTF cases arose. * Basically: If pop says this DTM is now empty, then return to the previous * if one exists, in whatever state we left it in. UGLY, but hopefully the * situation which forces us to consider this will arise exceedingly rarely. * */
public void popRTFContext() { int previous=m_last_pushed_rtfdtm.pop(); if(null==m_rtfdtm_stack) return; if(m_which_rtfdtm==previous) { if(previous>=0) // guard against none-active { boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark(); } } else while(m_which_rtfdtm!=previous) { // Empty each DTM before popping, so it's ready for reuse // _DON'T_ pop the previous, since it's still open (which is why we // stacked up more of these) and did not receive a mark. boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark(); --m_which_rtfdtm; } }
Gets DTMXRTreeFrag object if one has already been created. Creates new DTMXRTreeFrag object and adds to m_DTMXRTreeFrags HashMap, otherwise.
Params:
  • dtmIdentity –
Returns:DTMXRTreeFrag
/** * Gets DTMXRTreeFrag object if one has already been created. * Creates new DTMXRTreeFrag object and adds to m_DTMXRTreeFrags HashMap, * otherwise. * @param dtmIdentity * @return DTMXRTreeFrag */
public DTMXRTreeFrag getDTMXRTreeFrag(int dtmIdentity){ if(m_DTMXRTreeFrags == null){ m_DTMXRTreeFrags = new HashMap(); } if(m_DTMXRTreeFrags.containsKey(new Integer(dtmIdentity))){ return (DTMXRTreeFrag)m_DTMXRTreeFrags.get(new Integer(dtmIdentity)); }else{ final DTMXRTreeFrag frag = new DTMXRTreeFrag(dtmIdentity,this); m_DTMXRTreeFrags.put(new Integer(dtmIdentity),frag); return frag ; } }
Cleans DTMXRTreeFrag objects by removing references to DTM and XPathContext objects.
/** * Cleans DTMXRTreeFrag objects by removing references * to DTM and XPathContext objects. */
private final void releaseDTMXRTreeFrags(){ if(m_DTMXRTreeFrags == null){ return; } final Iterator iter = (m_DTMXRTreeFrags.values()).iterator(); while(iter.hasNext()){ DTMXRTreeFrag frag = (DTMXRTreeFrag)iter.next(); frag.destruct(); iter.remove(); } m_DTMXRTreeFrags = null; } }