You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by sb...@locus.apache.org on 2000/02/13 17:42:46 UTC
cvs commit: xml-xalan/src/org/apache/xalan/xslt AVTPartXPath.java Counter.java CountersTable.java ElemCallTemplate.java ElemExtensionCall.java ElemTemplateElement.java ElemValueOf.java Stylesheet.java StylesheetHandler.java XSLTEngineImpl.java
sboag 00/02/13 08:42:46
Modified: src makexpath4j
src/org/apache/xalan/xpath ExtensionFunctionHandler.java
FuncLast.java SimpleNodeLocator.java
UnionContext.java XLocator.java XPath.java
XPathProcessorImpl.java XPathSupport.java
XPathSupportDefault.java
src/org/apache/xalan/xpath/xml IntStack.java IntVector.java
NodeVector.java XMLParserLiaisonDefault.java
src/org/apache/xalan/xslt AVTPartXPath.java Counter.java
CountersTable.java ElemCallTemplate.java
ElemExtensionCall.java ElemTemplateElement.java
ElemValueOf.java Stylesheet.java
StylesheetHandler.java XSLTEngineImpl.java
Added: src/org/apache/xalan/xpath EmptyNodeListImpl.java
Log:
Implemented depth-first search for non-union single-step select patterns. This increases latency, esp. when used with the DTM.
Revision Changes Path
1.13 +1 -0 xml-xalan/src/makexpath4j
Index: makexpath4j
===================================================================
RCS file: /home/cvs/xml-xalan/src/makexpath4j,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- makexpath4j 2000/01/31 08:34:46 1.12
+++ makexpath4j 2000/02/13 16:42:40 1.13
@@ -70,6 +70,7 @@
$(XPATHDIR)$(PATHSEP)KeyDeclaration.java \
$(XPATHDIR)$(PATHSEP)MutableNodeList.java \
$(XPATHDIR)$(PATHSEP)MutableNodeListImpl.java \
+ $(XPATHDIR)$(PATHSEP)EmptyNodeListImpl.java \
$(XPATHDIR)$(PATHSEP)NodeListImpl.java \
$(XPATHDIR)$(PATHSEP)Process.java \
$(XPATHDIR)$(PATHSEP)SimpleNodeLocator.java \
1.7 +8 -6 xml-xalan/src/org/apache/xalan/xpath/ExtensionFunctionHandler.java
Index: ExtensionFunctionHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/ExtensionFunctionHandler.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- ExtensionFunctionHandler.java 1999/12/14 00:21:52 1.6
+++ ExtensionFunctionHandler.java 2000/02/13 16:42:41 1.7
@@ -71,13 +71,13 @@
*/
public class ExtensionFunctionHandler
{
- protected String namespaceUri; // uri of the extension namespace
- protected String scriptLang = "javaclass"; // scripting language of implementation
- protected String scriptSrc; // script source to run (if any)
- protected String scriptSrcURL; // URL of source of script (if any)
- protected Object javaObject = null; // object for javaclass engine
+ public String namespaceUri; // uri of the extension namespace
+ public String scriptLang = "javaclass"; // scripting language of implementation
+ public String scriptSrc; // script source to run (if any)
+ public String scriptSrcURL; // URL of source of script (if any)
+ public Object javaObject = null; // object for javaclass engine
protected boolean hasCalledCTor = false; // we'll be nice and call a ctor if they haven't
- protected Class classObject = null; // class object for javaclass engine
+ public Class classObject = null; // class object for javaclass engine
protected Hashtable functions = new Hashtable (); // functions of namespace
protected com.ibm.bsf.BSFManager mgr = null; // mgr used to run scripts
protected boolean componentStarted; // true when the scripts in a
@@ -239,7 +239,9 @@
if(!hasCalledCTor)
{
if(null == javaObject)
+ {
javaObject = this.classObject.newInstance();
+ }
argArray = new Object[args.size () + 1];
argArray[0] = javaObject;
1.3 +2 -1 xml-xalan/src/org/apache/xalan/xpath/FuncLast.java
Index: FuncLast.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/FuncLast.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- FuncLast.java 1999/11/28 10:26:15 1.2
+++ FuncLast.java 2000/02/13 16:42:41 1.3
@@ -74,7 +74,8 @@
* @return A valid XObject.
*/
public XObject execute(XPath path, XPathSupport execContext, Node context, int opPos, Vector args)
+ throws org.xml.sax.SAXException
{
- return new XNumber((double)path.getCountOfContextNodeList(execContext));
+ return new XNumber((double)path.getCountOfContextNodeList(path, execContext, context));
}
}
1.12 +511 -612 xml-xalan/src/org/apache/xalan/xpath/SimpleNodeLocator.java
Index: SimpleNodeLocator.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/SimpleNodeLocator.java,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- SimpleNodeLocator.java 2000/02/08 14:43:51 1.11
+++ SimpleNodeLocator.java 2000/02/13 16:42:41 1.12
@@ -71,6 +71,11 @@
public class SimpleNodeLocator implements XLocator, Serializable
{
/**
+ * Dev-time/QE switch to use optimized, depth-first search, or not.
+ */
+ public static boolean USEDEPTHFIRST = true;
+
+ /**
* Create a SimpleNodeLocator object.
*/
public SimpleNodeLocator()
@@ -83,6 +88,16 @@
private static SimpleNodeLocator m_locater = null;
/**
+ * Empty node list for failed results.
+ */
+ private static MutableNodeList emptyQueryResults = new EmptyNodeListImpl();
+
+ /**
+ * Empty node list for failed results.
+ */
+ private static XNodeSet emptyNodeList = new XNodeSet(emptyQueryResults);
+
+ /**
* The the default locator.
*/
public static XLocator getDefaultLocator()
@@ -108,7 +123,7 @@
m_locater = (null == m_locater) ? new SimpleNodeLocator() : m_locater;
return m_locater;
}
-
+
/**
* (Same as query for the moment).
* @param opPos The current position in the xpath.m_opMap array.
@@ -120,7 +135,7 @@
m_locater = (null == m_locater) ? new SimpleNodeLocator() : m_locater;
return m_locater;
}
-
+
/**
* Execute a connection (if it was not executed by the static
* connect method) and process the following LocationPath,
@@ -137,7 +152,7 @@
* @returns the result of the query in an XNodeSet object.
*/
public XNodeSet connectToNodes(XPath xpath, XPathSupport execContext, Node context,
- int opPos, Vector connectArgs)
+ int opPos, Vector connectArgs)
throws org.xml.sax.SAXException
{
String fileSpec = ((XObject)connectArgs.elementAt(0)).str();
@@ -170,9 +185,10 @@
Document doc = execContext.parseXML(url, null, null);
if(null != doc)
{
- if((xpath.OP_LOCATIONPATH == xpath.m_opMap[opPos]))
+ int op = xpath.m_opMap[opPos];
+ if(xpath.OP_LOCATIONPATH == (op & XPath.LOCATIONPATHEX_MASK))
{
- XNodeSet xnl = xpath.locationPath(execContext, doc, opPos);
+ XNodeSet xnl = xpath.locationPath(execContext, doc, opPos, null, null, false);
if(null != xnl)
{
mnl.addNodes(xnl.nodeset());
@@ -201,72 +217,11 @@
{
System.out.println("Filespec was bad in connect");
}
-
- return results;
- }
-
- /**
- * Analyze a union pattern and tell if the axes are
- * all descendants.
- */
- /*
- boolean isLocationPathAllDescendants(XPath xpath, int opPos)
- {
- int posOfLastOp = xpath.getNextOpPos(opPos)-1;
- opPos = xpath.getFirstChildPos(opPos);
- while(opPos < posOfLastOp)
- {
- // step
- int stepType = xpath.m_opMap[opPos];
-
- switch(stepType)
- {
- case xpath.FROM_SELF:
- case xpath.FROM_ATTRIBUTES: // ?
- case xpath.FROM_CHILDREN:
- // case xpath.FROM_DESCENDANTS:
- // case xpath.FROM_DESCENDANTS_OR_SELF:
- // case xpath.FROM_FOLLOWING: ...might do these later
- // case xpath.FROM_FOLLOWING_SIBLINGS: ...might do these later
- break;
- default:
- return false;
- }
-
- opPos = xpath.getNextOpPos(opPos);
- }
- if(xpath.m_opMap[opPos] != xpath.ENDOP)
- {
- System.out.println("ERROR! Could not find ENDOP after OP_LOCATIONPATH");
- }
- return true;
+ return results;
}
- */
-
/**
- * Analyze a union pattern and tell if the axes are
- * all descendants.
- */
- /*
- boolean isUnionOfDescendants(XPath xpath, int opPos)
- {
- opPos = xpath.getFirstChildPos(opPos);
- while(xpath.m_opMap[opPos] == xpath.OP_LOCATIONPATH)
- {
- int nextOpPos = xpath.getNextOpPos(opPos);
- if(!isLocationPathAllDescendants(xpath, opPos))
- {
- return false;
- }
- opPos = nextOpPos;
- }
- return true;
- }
- */
-
- /**
* Computes the union of its operands which must be node-sets.
* @param context The current source tree context node.
* @param opPos The current position in the m_opMap array.
@@ -274,44 +229,42 @@
* callback methods are used.
*/
public XNodeSet union(XPath xpath, XPathSupport execContext,
- Node context, int opPos)
+ Node context, int opPos,
+ NodeCallback callback,
+ Object callbackInfo)
throws org.xml.sax.SAXException
{
XNodeSet resultNodeSet = null;
- /*
- if(false && isUnionOfDescendants(xpath, opPos))
- {
- // If this is a union of all descendants, and doesn't
- // contain any indexes, then we can safely do a depth-first
- // walk, analyzing all the union at once, and execute call-backs
- // as soon as we locate the nodes.
+ opPos = xpath.getFirstChildPos(opPos);
- UnionContext unionContext = new UnionContext(xpath.m_opMap, opPos);
-
- MutableNodeList mnl = depthStep(xpath, execContext, context, unionContext, 1);
- }
- else
- */
+ while((xpath.m_opMap[opPos] & XPath.LOCATIONPATHEX_MASK) == xpath.OP_LOCATIONPATH)
{
+ int nextOpPos = xpath.getNextOpPos(opPos);
+
+ // XNodeSet expr = (XNodeSet)xpath.execute(execContext, context, opPos);
opPos = xpath.getFirstChildPos(opPos);
+ MutableNodeList mnl = step(xpath, execContext, context, opPos,
+ callback, callbackInfo, false, false);
+ XNodeSet expr = (null != mnl) ? new XNodeSet(mnl) : emptyNodeList;
- while(xpath.m_opMap[opPos] == xpath.OP_LOCATIONPATH)
+ if(null == resultNodeSet)
{
- int nextOpPos = xpath.getNextOpPos(opPos);
-
- XNodeSet expr = (XNodeSet)xpath.execute(execContext, context, opPos);
- if(null == resultNodeSet)
+ resultNodeSet = expr;
+ }
+ else if(expr != emptyNodeList)
+ {
+ if(resultNodeSet != emptyNodeList)
{
- resultNodeSet = expr;
+ MutableNodeList nl = resultNodeSet.mutableNodeset();
+ nl.addNodesInDocOrder(expr.nodeset(), execContext);
}
else
{
- MutableNodeList nl = resultNodeSet.mutableNodeset();
- nl.addNodesInDocOrder(expr.nodeset(), execContext);
+ resultNodeSet = expr;
}
- opPos = nextOpPos;
}
+ opPos = nextOpPos;
}
return resultNodeSet;
@@ -324,334 +277,39 @@
* the rest of the LocationPath, and then wraps the NodeList result
* in an XNodeSet object.
* @param xpath The xpath that is executing.
+ * @param execContext The execution context.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
* @returns the result of the query in an XNodeSet object.
*/
public XNodeSet locationPath(XPath xpath, XPathSupport execContext,
- Node context, int opPos)
+ Node context, int opPos,
+ NodeCallback callback,
+ Object callbackInfo, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
- opPos = xpath.getFirstChildPos(opPos);
XNodeSet results;
- MutableNodeList mnl = step(xpath, execContext, context, opPos);
- if(null != mnl)
+ boolean isSimpleFollowing = (0 != (xpath.m_opMap[opPos] & XPath.LOCATIONPATHEX_MASK));
+ opPos = xpath.getFirstChildPos(opPos);
+ MutableNodeList mnl;
+ try
{
- results = new XNodeSet(mnl);
+ mnl = step(xpath, execContext, context, opPos,
+ callback, callbackInfo, isSimpleFollowing, false);
}
- else
+ catch(FoundIndex fi)
{
- results = new XNodeSet(new MutableNodeListImpl());
+ mnl = step(xpath, execContext, context, opPos,
+ null, null, false, false);
}
-
- return results;
- }
-
- /**
- * For use by the depthStep function.
- */
- protected boolean testPredicates(XPath xpath,
- XPathSupport execContext,
- Node context,
- UnionContext unionContext,
- int opPos, int whichLocationPath)
- throws org.xml.sax.SAXException
- {
- boolean doNotFilter = true;
- int childPosOfStep = xpath.getFirstChildPosOfStep(opPos);
- int argLen = xpath.getArgLengthOfStep(opPos);
- childPosOfStep+=argLen;
- int nextStepType = xpath.m_opMap[childPosOfStep];
- while(xpath.OP_PREDICATE == nextStepType)
- {
- XObject pred = xpath.predicate(execContext, context, childPosOfStep);
- if(XObject.CLASS_NUMBER == pred.getType())
- {
- if(unionContext.getNodePosition(whichLocationPath) != (int)pred.num())
- {
- doNotFilter = false;
- }
- }
- else if(!pred.bool())
- {
- doNotFilter = false;
- }
- childPosOfStep = xpath.getNextOpPos(childPosOfStep);
- nextStepType = xpath.m_opMap[childPosOfStep];
- }
- return doNotFilter;
- }
-
- /**
- * Process the current stack of steps for the given
- * context node.
- * walkInstructions[0] will contain shouldWalkSubtree?
- * walkInstructions[1] will contain shouldWalkAttributes?
- * @return if the node should be processed.
- */
- boolean evalSteps(XPath xpath, XPathSupport execContext,
- Node context,
- UnionContext unionContext,
- int nLP,
- boolean hasChildNodes,
- boolean isSelf,
- boolean[] walkInstructions)
- throws org.xml.sax.SAXException
- {
- boolean shouldProcessNode = false;
- boolean shouldWalkSubtree = false; // Tell if we should walk the subtree.
- boolean shouldWalkAttributes = false; // Tell if we should walk the subtree.
-
- for(int i = 0; i < nLP; i++)
- {
- int opPos = unionContext.peek(i);
- int stepType;
- int argLen = 0;
- if(UnionContext.PSUEDO_POS_FOUNDNODE == opPos)
- {
- stepType = UnionContext.PSUEDO_OP_FOUNDNODE;
- argLen = 0;
- }
- else
- {
- stepType = xpath.m_opMap[opPos];
- int posOfNext = xpath.getNextOpPos(opPos);
- int nextStepType = xpath.m_opMap[posOfNext];
-
- if(!isSelf || (stepType == XPath.FROM_DESCENDANTS_OR_SELF) ||
- (stepType == XPath.FROM_SELF))
- {
- int childPosOfStep = xpath.getFirstChildPosOfStep(opPos);
- argLen = xpath.getArgLengthOfStep(opPos);
- // System.out.println("Testing: "+context.getNodeName());
- int origStepType = stepType;
- int posOfNextIfSuccess;
- if((stepType == XPath.FROM_DESCENDANTS) ||
- (stepType == XPath.FROM_DESCENDANTS_OR_SELF))
- {
- childPosOfStep = xpath.getFirstChildPosOfStep(posOfNext);
- argLen = xpath.getArgLengthOfStep(posOfNext);
- posOfNextIfSuccess = xpath.getNextOpPos(posOfNext);
- stepType = nextStepType;
- }
- else
- {
- posOfNextIfSuccess = posOfNext;
- }
- if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext,
- context, childPosOfStep,
- argLen, stepType))
- {
- // NodeList savedContextNodeList = execContext.getContextNodeList();
- // execContext.setContextNodeList(queryResults);
- boolean doNotFilter = testPredicates(xpath,
- execContext,
- context,
- unionContext,
- opPos, i);
-
- opPos = doNotFilter ? posOfNext : UnionContext.PSUEDO_POS_FOUNDNODE;
- argLen = 0;
-
- if(opPos != UnionContext.PSUEDO_POS_FOUNDNODE)
- {
- if(XPath.ENDOP == nextStepType)
- {
- if(!((origStepType == XPath.FROM_DESCENDANTS) ||
- (origStepType == XPath.FROM_DESCENDANTS_OR_SELF)))
- {
- stepType = UnionContext.PSUEDO_OP_FOUNDNODE;
- }
- shouldProcessNode = true;
- }
- else
- {
- shouldWalkSubtree = true;
- if((false == shouldWalkAttributes) && (nextStepType == XPath.FROM_ATTRIBUTES))
- {
- shouldWalkAttributes = true;
- }
- }
- unionContext.incrementNodePosition(i);
- }
- }
- if(hasChildNodes)
- {
- argLen = 0; // Do not increment to next expression position.
-
- // If this is a FROM_DESCENDANTS or FROM_DESCENDANTS_OR_SELF, then
- // continue to process, otherwise push a PSUEDO_POS_FOUNDNODE so
- // the processing for this expression will stop for the next
- // level in the tree.
- if(!((origStepType == XPath.FROM_DESCENDANTS) ||
- (origStepType == XPath.FROM_DESCENDANTS_OR_SELF)))
- {
- // Even though we didn't find the node, setting it thus
- // will prevent us from continuing to process this LocationPath.
- opPos = UnionContext.PSUEDO_POS_FOUNDNODE;
- }
- }
- }
- else // if not testing the self node
- {
- shouldWalkSubtree = true; // we'll need to continue to children
- }
- }
- if(hasChildNodes)
- {
- opPos = opPos += argLen;
- unionContext.push(i, opPos, 1);
- }
- } // end for(int i = 0; i < nLP; i++)
-
- if(null != walkInstructions)
- {
- walkInstructions[0] = shouldWalkSubtree;
- walkInstructions[1] = shouldWalkAttributes;
- }
-
- return shouldProcessNode;
- }
+ results = (null != mnl) ? new XNodeSet(mnl) : emptyNodeList;
+ return results;
+ }
/**
- * Execute a step and predicates in a location path, walking the
- * tree depth first, and executing the callback method (if there
- * is one) as soon as the node is located. This method should
- * only be called when all steps in the LocationPaths are going
- * to be on the forward axes.
- * @param xpath The xpath that is executing.
- * @param context The current source tree context node.
- * @param opPos The current position in the xpath.m_opMap array.
- * @returns a node-set.
- * @see org.apache.xalan.xpath.SimpleNodeLocator#step(XPath xpath, XPathSupport execContext, Node context, int opPos)
- */
- protected MutableNodeList depthStep(XPath xpath,
- XPathSupport execContext,
- Node context,
- UnionContext unionContext,
- int indexPos)
- throws org.xml.sax.SAXException
- {
- MutableNodeList queryResults = new MutableNodeListImpl();
-
- Node top = context;
NodeCallback callback = execContext.getCallback();
- Object callbackInfo = execContext.getCallbackInfo();
- execContext.setCallback(null, null);
-
- // We have to flag if we're at the top of the tree, so we
- // don't try to process the self node for FROM_CHILDREN, etc.
- // This is faster than context.equals(top).
- boolean isSelf = true;
-
- // The number of location paths is constant throughout the
- // tree walk.
- int nLP = unionContext.getLocationPathCount();
- boolean[] walkInstructions = {false, false};
-
- while(null != context)
- {
- boolean hasChildNodes = (context.getNodeType() != Node.ATTRIBUTE_NODE) ?
- context.hasChildNodes() : false;
-
- boolean shouldProcess = evalSteps(xpath, execContext,
- context, unionContext, nLP,
- hasChildNodes, isSelf,
- walkInstructions);
- boolean shouldWalkSubtree = walkInstructions[0];
- boolean shouldWalkAttributes = walkInstructions[1];
-
- if(shouldProcess)
- {
- if(null != callback)
- callback.processLocatedNode(execContext, context, callbackInfo);
- else
- queryResults.addNode(context);
- }
-
- // We have to do a special walk for the attributes.
- if(shouldWalkAttributes)
- {
- // If they're no child nodes, he
- // to go and push the next steps on the stack, since
- // they were not pushed by evalSteps (the reason is a long story...).
- // Only need to push FROM_ATTRIBUTES, the rest can go on as
- // PSUEDO_POS_FOUNDNODE, to avoid extra work.
- if(!hasChildNodes)
- {
- for(int x = 0; x < nLP; x++)
- {
- int nextOpPos = unionContext.peek(x);
- if(UnionContext.PSUEDO_POS_FOUNDNODE != nextOpPos)
- {
- nextOpPos = xpath.getNextOpPos(nextOpPos);
- if(!(XPath.FROM_ATTRIBUTES == xpath.m_opMap[nextOpPos]))
- nextOpPos = UnionContext.PSUEDO_POS_FOUNDNODE;
- }
- unionContext.push(x, nextOpPos, 1);
- }
- }
- NamedNodeMap attrs = context.getAttributes();
- int n = attrs.getLength();
- for(int k = 0; k < n; k++)
- {
- shouldProcess = evalSteps(xpath, execContext,
- attrs.item(k), unionContext, nLP,
- false, isSelf, null);
- if(shouldProcess)
- {
- if(null != callback)
- callback.processLocatedNode(execContext, attrs.item(k), callbackInfo);
- else
- queryResults.addNode(context);
- }
- }
- if(!hasChildNodes)
- unionContext.pop(); // pop what we just pushed, ready for children.
- }
-
- if(isSelf)
- isSelf = false;
-
- // If this node has child nodes, but all patterns are complete
- // or failed, then we don't want to walk the subtree, so we
- // have to pop the stack that was pushed in anticipation of
- // processing the children.
- Node nextNode;
- if(shouldWalkSubtree && hasChildNodes)
- {
- nextNode = context.getFirstChild();
- }
- else
- {
- nextNode = null;
- if(hasChildNodes)
- unionContext.pop(); // pop all the positions.
- }
-
- while(null == nextNode)
- {
- if(top.equals( context ))
- break;
- nextNode = context.getNextSibling();
- if(null == nextNode)
- {
- unionContext.pop(); // pop all the positions.
- context = context.getParentNode();
- if((null == context) || (top.equals( context )))
- {
- nextNode = null;
- break;
- }
- }
- }
- context = nextNode;
- }
-
- return queryResults;
- }
-
- /**
* Execute a step and predicates in a location path. This recursivly
* executes each of the steps and predicates.
* The step can be oneof xpath.OP_VARIABLE, OP_EXTFUNCTION,
@@ -673,157 +331,257 @@
* @param opPos The current position in the xpath.m_opMap array.
* @returns a node-set.
*/
- protected MutableNodeList step(XPath xpath, XPathSupport execContext, Node context, int opPos)
+ protected MutableNodeList step(XPath xpath, XPathSupport execContext,
+ Node context, int opPos,
+ NodeCallback callback, Object callbackInfo,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
// int endStep = xpath.getNextOpPos(opPos);
int stepType = xpath.m_opMap[opPos];
- int argLen;
- MutableNodeList subQueryResults = new MutableNodeListImpl();
+ int argLen = 200; // dummy val to shut up compiler
+ MutableNodeList subQueryResults = null;
MutableNodeList queryResults = null;
boolean shouldReorder = false;
boolean continueStepRecursion = true;
boolean mightHaveToChangeLocators = false;
- switch(stepType)
+ boolean variableArgLen = false;
+
+ if(isSimpleFollowing && (null != callback))
+ execContext.pushContextNodePosition();
+
+ // If the step has an index predicate, which we won't know until after the
+ // predicate is evaluated, and isSimpleFollowing is true,
+ // then a FoundIndex exception will be thrown, and we'll try again with
+ // a full blown vector search. This will not be good at all for a few
+ // cases, but for the majority cases, the isSimpleFollowing optimization
+ // is worth it.
+ for(int i = 0; i < 2; i++)
{
- case XPath.OP_VARIABLE:
- case XPath.OP_EXTFUNCTION:
- case XPath.OP_FUNCTION:
- case XPath.OP_GROUP:
- argLen = findNodeSet(xpath, execContext, context, opPos,
- stepType, subQueryResults);
- mightHaveToChangeLocators = true;
- break;
- case XPath.FROM_ROOT:
- argLen = findRoot(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_PARENT:
- argLen = findParent(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_SELF:
- argLen = findSelf(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_ANCESTORS:
- argLen = findAncestors(xpath, execContext, context, opPos, stepType, subQueryResults);
- shouldReorder = true;
- break;
- case XPath.FROM_ANCESTORS_OR_SELF:
- argLen = findAncestorsOrSelf(xpath, execContext, context, opPos, stepType, subQueryResults);
- shouldReorder = true;
- break;
- case XPath.MATCH_ATTRIBUTE:
- continueStepRecursion = false;
- // fall-through on purpose.
- case XPath.FROM_ATTRIBUTES:
- argLen = findAttributes(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.MATCH_ANY_ANCESTOR:
- case XPath.MATCH_IMMEDIATE_ANCESTOR:
- continueStepRecursion = false;
- // fall-through on purpose.
- case XPath.FROM_CHILDREN:
- argLen = findChildren(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_DESCENDANTS:
- case XPath.FROM_DESCENDANTS_OR_SELF:
- argLen = findDescendants(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_FOLLOWING:
- argLen = findFollowing(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_FOLLOWING_SIBLINGS:
- argLen = findFollowingSiblings(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- case XPath.FROM_PRECEDING:
- argLen = findPreceding(xpath, execContext, context, opPos, stepType, subQueryResults);
- shouldReorder = true;
- break;
- case XPath.FROM_PRECEDING_SIBLINGS:
- argLen = findPrecedingSiblings(xpath, execContext, context, opPos, stepType, subQueryResults);
- shouldReorder = true;
- break;
- case XPath.FROM_NAMESPACE:
- argLen = findNamespace(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
- default:
- argLen = findNodesOnUnknownAxis(xpath, execContext, context, opPos, stepType, subQueryResults);
- break;
+ try
+ {
+ switch(stepType)
+ {
+ case xpath.OP_VARIABLE:
+ case xpath.OP_EXTFUNCTION:
+ case xpath.OP_FUNCTION:
+ case xpath.OP_GROUP:
+ subQueryResults = new MutableNodeListImpl();
+ argLen = findNodeSet(xpath, execContext, context, opPos,
+ stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ mightHaveToChangeLocators = true;
+ variableArgLen = true;
+ break;
+ case XPath.FROM_ROOT:
+ subQueryResults = findRoot(xpath, execContext, context, opPos,
+ stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_PARENT:
+ subQueryResults = findParent(xpath, execContext, context, opPos,
+ stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_SELF:
+ subQueryResults = findSelf(xpath, execContext, context, opPos, stepType, subQueryResults,
+ callback, callbackInfo, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_ANCESTORS:
+ subQueryResults = findAncestors(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ shouldReorder = true;
+ break;
+ case XPath.FROM_ANCESTORS_OR_SELF:
+ subQueryResults = findAncestorsOrSelf(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ shouldReorder = true;
+ break;
+ case xpath.MATCH_ATTRIBUTE:
+ continueStepRecursion = false;
+ // fall-through on purpose.
+ case XPath.FROM_ATTRIBUTES:
+ subQueryResults = findAttributes(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ case xpath.MATCH_ANY_ANCESTOR:
+ case xpath.MATCH_IMMEDIATE_ANCESTOR:
+ continueStepRecursion = false;
+ // fall-through on purpose.
+ case XPath.FROM_CHILDREN:
+ subQueryResults = findChildren(xpath, execContext, context, opPos, stepType, subQueryResults,
+ callback, callbackInfo, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_DESCENDANTS:
+ case XPath.FROM_DESCENDANTS_OR_SELF:
+ subQueryResults = findDescendants(xpath, execContext, context, opPos, stepType, subQueryResults,
+ callback, callbackInfo, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_FOLLOWING:
+ subQueryResults = findFollowing(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_FOLLOWING_SIBLINGS:
+ subQueryResults = findFollowingSiblings(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ case XPath.FROM_PRECEDING:
+ subQueryResults = findPreceding(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ shouldReorder = true;
+ break;
+ case XPath.FROM_PRECEDING_SIBLINGS:
+ subQueryResults = findPrecedingSiblings(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ shouldReorder = true;
+ break;
+ case XPath.FROM_NAMESPACE:
+ subQueryResults = findNamespace(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ default:
+ subQueryResults = findNodesOnUnknownAxis(xpath, execContext, context, opPos, stepType, subQueryResults, isSimpleFollowing, stopAtFirst);
+ break;
+ }
+
+ break; // from loop of 2
+ }
+ catch(FoundIndex fi)
+ {
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.popContextNodePosition();
+ subQueryResults = new MutableNodeListImpl();
+ isSimpleFollowing = false;
+ stopAtFirst = false;
+ }
+ else
+ {
+ throw fi;
+ }
+ }
+ finally
+ {
+ if(isSimpleFollowing && (null != callback))
+ execContext.popContextNodePosition();
+ }
}
+
+ if(null == subQueryResults)
+ return null;
+
+ if(!variableArgLen)
+ argLen = xpath.getArgLengthOfStep(opPos)+3;
+
opPos += argLen;
int nextStepType = xpath.m_opMap[opPos];
-
- NodeList savedContextNodeList = execContext.getContextNodeList();
- execContext.setContextNodeList(subQueryResults);
- if(xpath.OP_PREDICATE == nextStepType)
+ try
{
- int[] endPredicatesPos =
+ execContext.pushContextNodeList(subQueryResults);
+
+ if(xpath.OP_PREDICATE == nextStepType)
{
- -42};
- subQueryResults = predicates(xpath, execContext, context, opPos,
- subQueryResults, endPredicatesPos);
- opPos = endPredicatesPos[0];
- nextStepType = xpath.m_opMap[opPos];
- }
+ int[] endPredicatesPos =
+ {
+ -42};
+ subQueryResults = predicates(xpath, execContext, context, opPos,
+ subQueryResults, endPredicatesPos);
+ opPos = endPredicatesPos[0];
+ nextStepType = xpath.m_opMap[opPos];
+ }
- XLocator xlocator = this;
- if((xpath.ENDOP != nextStepType) && continueStepRecursion)
- {
- int nContexts = subQueryResults.getLength();
- for(int i = 0; i < nContexts; i++)
+ if(null == subQueryResults)
+ return null;
+
+ XLocator xlocator = this;
+ if((xpath.ENDOP != nextStepType) && continueStepRecursion)
{
- Node node = subQueryResults.item(i);
- if(null != node)
+ int nContexts = subQueryResults.getLength();
+ for(int i = 0; i < nContexts; i++)
{
- if(mightHaveToChangeLocators)
- {
- xlocator = execContext.getXLocatorFromNode(node);
- }
- MutableNodeList mnl = step(xpath, execContext, node, opPos);
- if(queryResults == null)
+ Node node = subQueryResults.item(i);
+ if(null != node)
{
- queryResults = mnl;
- }
- else
- {
- queryResults.addNodesInDocOrder(mnl, execContext);
+ if(mightHaveToChangeLocators)
+ {
+ xlocator = execContext.getXLocatorFromNode(node);
+ }
+ MutableNodeList mnl = step(xpath, execContext, node, opPos, null, null, false, false);
+ if((null != mnl) && mnl != this.emptyNodeList)
+ {
+ if(queryResults == null)
+ {
+ queryResults = mnl;
+ }
+ else
+ {
+ queryResults.addNodesInDocOrder(mnl, execContext);
+ }
+ }
}
}
}
- if(null == queryResults)
+ else
{
- queryResults = new MutableNodeListImpl();
+ if(shouldReorder)
+ {
+ queryResults = new MutableNodeListImpl();
+ queryResults.addNodesInDocOrder(subQueryResults, execContext);
+ }
+ else
+ {
+ queryResults = subQueryResults;
+ }
}
}
- else
+ finally
{
- if(shouldReorder)
- {
- queryResults = new MutableNodeListImpl();
- queryResults.addNodesInDocOrder(subQueryResults, execContext);
- }
- else
- {
- queryResults = subQueryResults;
- }
+ execContext.popContextNodeList();
}
- execContext.setContextNodeList(savedContextNodeList);
+
return queryResults;
}
/**
+ * Add a node to a node list, but lazily create the node list if
+ * it doesn't already exist.
+ */
+ private final MutableNodeList addNode(MutableNodeList subQueryResults, Node node)
+ {
+ if(null == subQueryResults)
+ subQueryResults = new MutableNodeListImpl(node);
+ else
+ subQueryResults.addNode(node);
+ return subQueryResults;
+ }
+
+ /**
+ * Add a node to a node list, but lazily create the node list if
+ * it doesn't already exist.
+ */
+ private final MutableNodeList addNodeInDocOrder(XPathSupport execContext, MutableNodeList subQueryResults, Node node)
+ {
+ if(null == subQueryResults)
+ subQueryResults = new MutableNodeListImpl(node);
+ else
+ subQueryResults.addNodeInDocOrder(node, execContext);
+ return subQueryResults;
+ }
+
+ /**
+ * Add a node to the ContextNodeList, if we're doing depth-first
+ * traversal.
+ */
+ void addToContextNodeList(XPathSupport execContext, Node n)
+ {
+ }
+
+
+ /**
* Add the context to the list if it meets the NodeTest qualification.
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_SELF.
+ * @param stepType Value of XPath.FROM_SELF.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findSelf(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findSelf(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ NodeCallback callback, Object callbackInfo,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -832,14 +590,38 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context, opPos, argLen, stepType))
{
- subQueryResults.addNode(context);
+ // subQueryResults.addNode(context);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(context);
+ if(predicate(xpath, execContext, context, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, context, callbackInfo);
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, context);
+ }
}
}
else
{
- subQueryResults.addNode(context);
+ // subQueryResults.addNode(context);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(context);
+ if(predicate(xpath, execContext, context, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, context, callbackInfo);
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, context);
+ }
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -848,14 +630,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_ATTRIBUTES.
+ * @param stepType Value of XPath.FROM_ATTRIBUTES.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findAttributes(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findAttributes(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -871,12 +654,13 @@
Attr attr = (Attr)attributeList.item(j);
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, attr, opPos, argLen, stepType))
{
- subQueryResults.addNode(attr);
+ subQueryResults = addNode(subQueryResults, attr);
+ // If we have an attribute name here, we can quit.
}
}
}
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -885,14 +669,17 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_CHILDREN.
+ * @param stepType Value of XPath.FROM_CHILDREN.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findChildren(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findChildren(XPath xpath, XPathSupport execContext, Node context,
+ int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ NodeCallback callback, Object callbackInfo,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -908,7 +695,21 @@
{
// or else call execute method. If no execute method,
// add the node.
- subQueryResults.addNode(c);
+ // subQueryResults.addNode(c);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(c);
+ if(predicate(xpath, execContext, c, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, c, callbackInfo);
+ if(stopAtFirst)
+ break;
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, c);
+ }
}
c = c.getNextSibling();
}
@@ -922,12 +723,26 @@
Node c = children.item(i);
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, c, opPos, argLen, stepType))
{
- subQueryResults.addNode(c);
+ // subQueryResults.addNode(c);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(c);
+ if(predicate(xpath, execContext, c, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, c, callbackInfo);
+ if(stopAtFirst)
+ break;
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, c);
+ }
}
c = c.getNextSibling();
}
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -937,14 +752,17 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_DESCENDANTS or xpath.FROM_DESCENDANTS_OR_SELF.
+ * @param stepType Value of XPath.FROM_DESCENDANTS or XPath.FROM_DESCENDANTS_OR_SELF.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findDescendants(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findDescendants(XPath xpath, XPathSupport execContext,
+ Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ NodeCallback callback, Object callbackInfo,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -970,11 +788,25 @@
{
while(null != pos)
{
- if((stepType == xpath.FROM_DESCENDANTS_OR_SELF) || (context != pos))
+ if((stepType == XPath.FROM_DESCENDANTS_OR_SELF) || (context != pos))
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, pos, opPos, argLen, stepType))
{
- subQueryResults.addNode(pos);
+ // subQueryResults.addNode(pos);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(pos);
+ if(predicate(xpath, execContext, pos, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, pos, callbackInfo);
+ if(stopAtFirst)
+ break;
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, pos);
+ }
}
}
Node nextNode = pos.getFirstChild();
@@ -1006,11 +838,24 @@
context = pos;
while(null != pos)
{
- if((stepType == xpath.FROM_DESCENDANTS_OR_SELF) || (!context.equals( pos )))
+ if((stepType == XPath.FROM_DESCENDANTS_OR_SELF) || (!context.equals( pos )))
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, pos, opPos, argLen, stepType))
{
- subQueryResults.addNode(pos);
+ if(isSimpleFollowing && (null != callback))
+ {
+ execContext.incrementContextNodePosition(pos);
+ if(predicate(xpath, execContext, pos, opPos+argLen))
+ {
+ callback.processLocatedNode(execContext, pos, callbackInfo);
+ if(stopAtFirst)
+ break;
+ }
+ }
+ else
+ {
+ subQueryResults = addNode(subQueryResults, pos);
+ }
}
}
Node nextNode = pos.getFirstChild();
@@ -1033,7 +878,7 @@
}
}
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1050,14 +895,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_FOLLOWING.
+ * @param stepType Value of XPath.FROM_FOLLOWING.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findFollowing(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findFollowing(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1073,7 +919,7 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, pos, opPos, argLen, stepType))
{
- subQueryResults.addNodeInDocOrder(pos, execContext);
+ subQueryResults = addNodeInDocOrder(execContext, subQueryResults, pos);
}
nextNode = pos.getFirstChild();
}
@@ -1096,7 +942,7 @@
}
pos = nextNode;
}
- return argLen+3;
+ return subQueryResults;
}
@@ -1107,14 +953,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_FOLLOWING_SIBLINGS.
+ * @param stepType Value of XPath.FROM_FOLLOWING_SIBLINGS.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findFollowingSiblings(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findFollowingSiblings(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1125,11 +972,11 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, pos, opPos, argLen, stepType))
{
- subQueryResults.addNode(pos);
+ subQueryResults = addNode(subQueryResults, pos);
}
pos = pos.getNextSibling();
}
- return argLen+3;
+ return subQueryResults;
}
@@ -1147,19 +994,20 @@
* or end of step).
*/
protected int findNodeSet(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
- XObject obj = xpath.execute(execContext, context, opPos);
- NodeList nl = obj.nodeset();
-
- // Should this be adding in doc order?
- // We can not simply assign the nl value to
- // subQueryResults, because nl may be a ref to
- // a variable or the like, and we may mutate
- // below... which results in a hard-to-find bug!
- subQueryResults.addNodes(nl);
- return xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH];
+ XObject obj = xpath.execute(execContext, context, opPos);
+ NodeList nl = obj.nodeset();
+
+ // Should this be adding in doc order?
+ // We can not simply assign the nl value to
+ // subQueryResults, because nl may be a ref to
+ // a variable or the like, and we may mutate
+ // below... which results in a hard-to-find bug!
+ subQueryResults.addNodes(nl);
+ return xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH];
}
/**
@@ -1167,14 +1015,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_ROOT.
+ * @param stepType Value of XPath.FROM_ROOT.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findRoot(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findRoot(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1182,8 +1031,8 @@
Document docContext = (Node.DOCUMENT_NODE == context.getNodeType())
? (Document)context : context.getOwnerDocument();
- subQueryResults.addNode(docContext);
- return argLen+3;
+ subQueryResults = addNode(subQueryResults, docContext);
+ return subQueryResults;
}
/**
@@ -1191,14 +1040,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_PARENT.
+ * @param stepType Value of XPath.FROM_PARENT.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findParent(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findParent(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
context = execContext.getParentOfNode(context);
@@ -1210,15 +1060,15 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context, opPos, argLen, stepType))
{
- subQueryResults.addNode(context);
+ subQueryResults = addNode(subQueryResults, context);
}
}
else
{
- subQueryResults.addNode(context);
+ subQueryResults = addNode(subQueryResults, context);
}
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1226,14 +1076,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_ANCESTORS.
+ * @param stepType Value of XPath.FROM_ANCESTORS.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findAncestors(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findAncestors(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
context = execContext.getParentOfNode(context);
@@ -1243,27 +1094,28 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context, opPos, argLen, stepType))
{
- subQueryResults.addNode(context);
+ subQueryResults = addNode(subQueryResults, context);
}
context = execContext.getParentOfNode(context);
}
- return argLen+3;
+ return subQueryResults;
}
-
+
/**
* Add ancestors or the context to the list if they meet
* the NodeTest qualification.
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_ANCESTORS_OR_SELF.
+ * @param stepType Value of XPath.FROM_ANCESTORS_OR_SELF.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findAncestorsOrSelf(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findAncestorsOrSelf(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1272,11 +1124,11 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context, opPos, argLen, stepType))
{
- subQueryResults.addNode(context);
+ subQueryResults = addNode(subQueryResults, context);
}
context = execContext.getParentOfNode(context);
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1293,14 +1145,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_PRECEDING.
+ * @param stepType Value of XPath.FROM_PRECEDING.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findPreceding(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findPreceding(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1332,7 +1185,10 @@
if(!isParent)
{
- subQueryResults.insertNode(pos, 0);
+ if(null == subQueryResults)
+ subQueryResults = new MutableNodeListImpl(pos);
+ else
+ subQueryResults.insertNode(pos, 0);
}
}
Node nextNode = pos.getFirstChild();
@@ -1353,7 +1209,7 @@
}
pos = nextNode;
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1362,14 +1218,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_PRECEDING_SIBLINGS.
+ * @param stepType Value of XPath.FROM_PRECEDING_SIBLINGS.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findPrecedingSiblings(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findPrecedingSiblings(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
@@ -1380,11 +1237,11 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, pos, opPos, argLen, stepType))
{
- subQueryResults.addNode(pos);
+ subQueryResults = addNode(subQueryResults, pos);
}
pos = pos.getPreviousSibling();
}
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1392,20 +1249,21 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_NAMESPACE.
+ * @param stepType Value of XPath.FROM_NAMESPACE.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findNamespace(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findNamespace(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
opPos = xpath.getFirstChildPosOfStep(opPos);
xpath.error(context, XPATHErrorResources.ER_NAMESPACEAXIS_NOT_IMPLEMENTED); //"namespace axis not implemented yet!");
- return argLen+3;
+ return subQueryResults;
}
/**
@@ -1413,20 +1271,54 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
- * @param stepType Value of xpath.FROM_NAMESPACE.
+ * @param stepType Value of XPath.FROM_NAMESPACE.
* @param subQueryResults Should be an empty node list where the
* results of the step will be put.
* @returns the length of the argument (i.e. amount to add to predicate pos
* or end of step).
*/
- protected int findNodesOnUnknownAxis(XPath xpath, XPathSupport execContext, Node context, int opPos,
- int stepType, MutableNodeList subQueryResults)
+ protected MutableNodeList findNodesOnUnknownAxis(XPath xpath, XPathSupport execContext, Node context, int opPos,
+ int stepType, MutableNodeList subQueryResults,
+ boolean isSimpleFollowing, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
int argLen = xpath.getArgLengthOfStep(opPos);
opPos = xpath.getFirstChildPosOfStep(opPos);
- xpath.error(context, XPATHErrorResources.ER_UNKNOWN_AXIS, new Object[] {Integer.toString(stepType)}); //"unknown axis: "+stepType);
- return argLen+3;
+ xpath.error(context, XPATHErrorResources.ER_UNKNOWN_AXIS, new Object[] {Integer.toString(stepType)}); //"unknown axis: "+stepType);
+ return subQueryResults;
+ }
+
+ /**
+ * Execute a single predicate for a single node.
+ * @returns True if the node should not be filtered.
+ */
+ protected boolean predicate(XPath xpath, XPathSupport execContext, Node context, int opPos)
+ throws org.xml.sax.SAXException
+ {
+ boolean shouldNotFilter = true;
+
+ int nextStepType = xpath.m_opMap[opPos];
+ if(xpath.OP_PREDICATE == nextStepType)
+ {
+ execContext.pushDummyXPathContext();
+ try
+ {
+ XObject pred = xpath.predicate(execContext, context, opPos);
+ if(XObject.CLASS_NUMBER == pred.getType())
+ {
+ throw new FoundIndex(); // Ugly, but... see comment in the Step function.
+ }
+ else if(!pred.bool())
+ {
+ shouldNotFilter = false;
+ }
+ }
+ finally
+ {
+ execContext.popXPathContext();
+ }
+ }
+ return shouldNotFilter;
}
@@ -1472,21 +1364,23 @@
{
// This will reconstruct the node list without the nulls.
subQueryResults = new MutableNodeListImpl(subQueryResults);
-
- execContext.setContextNodeList(subQueryResults);
+
+ execContext.popContextNodeList();
+ execContext.pushContextNodeList(subQueryResults);
// Don't break, loop 'till end so that opPos will be set to end.
// if(0 == subQueryResults.getLength())
// break;
}
}
- endPredicatesPos[0] = opPos;
+ if(null != endPredicatesPos)
+ endPredicatesPos[0] = opPos;
if(hasNulls)
{
subQueryResults = new MutableNodeListImpl(subQueryResults);
}
return subQueryResults;
}
-
+
/**
* Execute a a location path pattern. This will return a score
* of MATCH_SCORE_NONE, MATCH_SCORE_NODETEST,
@@ -1501,7 +1395,9 @@
throws org.xml.sax.SAXException
{
opPos = xpath.getFirstChildPos(opPos);
- double[] scoreHolder = {xpath.MATCH_SCORE_NONE};
+ double[] scoreHolder =
+ {
+ xpath.MATCH_SCORE_NONE};
stepPattern(xpath, execContext, context, opPos, scoreHolder);
return scoreHolder[0];
}
@@ -1578,7 +1474,7 @@
{
argLen = xpath.getArgLengthOfStep(opPos);
opPos = xpath.getFirstChildPosOfStep(opPos);
- score = nodeTest(xpath, execContext, context, opPos, argLen, xpath.FROM_ATTRIBUTES);
+ score = nodeTest(xpath, execContext, context, opPos, argLen, XPath.FROM_ATTRIBUTES);
break;
}
case XPath.MATCH_ANY_ANCESTOR:
@@ -1662,7 +1558,7 @@
// easiest way.
execContext.setThrowFoundIndex(false);
Node parentContext = execContext.getParentOfNode(context);
- MutableNodeList mnl = step(xpath, execContext, parentContext, startOpPos);
+ MutableNodeList mnl = step(xpath, execContext, parentContext, startOpPos, null, null, false, false);
int nNodes = mnl.getLength();
score = xpath.MATCH_SCORE_NONE;
for(int i = 0; i < nNodes; i++)
@@ -1681,7 +1577,7 @@
if((scoreHolder[0] == xpath.MATCH_SCORE_NONE) ||
(score == xpath.MATCH_SCORE_NONE))
scoreHolder[0] = score;
-
+
return (score == xpath.MATCH_SCORE_NONE) ? null : context;
}
@@ -1711,7 +1607,7 @@
break;
case XPath.NODETYPE_TEXT:
score = (((Node.CDATA_SECTION_NODE == nodeType)
- || (Node.TEXT_NODE == nodeType)) &&
+ || (Node.TEXT_NODE == nodeType)) &&
(!execContext.shouldStripSourceNode(context)))
? xpath.MATCH_SCORE_NODETEST : xpath.MATCH_SCORE_NONE;
break;
@@ -1744,7 +1640,7 @@
|| (Node.TEXT_NODE == nodeType))
{
score = (!execContext.shouldStripSourceNode(context))
- ? xpath.MATCH_SCORE_NODETEST : xpath.MATCH_SCORE_NONE;
+ ? xpath.MATCH_SCORE_NODETEST : xpath.MATCH_SCORE_NONE;
}
else
{
@@ -1759,6 +1655,9 @@
case XPath.NODENAME:
{
+ if(!((Node.ATTRIBUTE_NODE == nodeType) || (Node.ELEMENT_NODE == nodeType)))
+ return xpath.MATCH_SCORE_NONE;
+
boolean test;
int queueIndex = xpath.m_opMap[opPos];
String targetNS = (queueIndex >= 0) ? (String)xpath.m_tokenQueue[xpath.m_opMap[opPos]]
@@ -1811,7 +1710,7 @@
switch(nodeType)
{
case Node.ATTRIBUTE_NODE:
- if(stepType == xpath.FROM_ATTRIBUTES)
+ if(stepType == XPath.FROM_ATTRIBUTES)
{
if(xpath.ELEMWILDCARD == queueIndex)
@@ -1823,7 +1722,7 @@
|| attrName.equals("xmlns"))))
? xpath.MATCH_SCORE_NODETEST
: xpath.MATCH_SCORE_NONE;
- }
+ }
else
{
score = xpath.MATCH_SCORE_NODETEST;
@@ -1844,7 +1743,7 @@
break;
case Node.ELEMENT_NODE:
- if(stepType != xpath.FROM_ATTRIBUTES)
+ if(stepType != XPath.FROM_ATTRIBUTES)
{
if(xpath.ELEMWILDCARD == queueIndex)
{
@@ -1866,7 +1765,7 @@
default:
// Trying to match on anything else causes nasty bugs.
- score = xpath.MATCH_SCORE_NONE;
+ score = xpath.MATCH_SCORE_NONE;
break;
} // end switch(nodeType)
1.2 +412 -62 xml-xalan/src/org/apache/xalan/xpath/UnionContext.java
Index: UnionContext.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/UnionContext.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- UnionContext.java 1999/12/13 08:06:01 1.1
+++ UnionContext.java 2000/02/13 16:42:41 1.2
@@ -59,16 +59,77 @@
import org.apache.xalan.xpath.xml.IntStack;
/**
- * Tracks multiple stacks of opcodes positions.
+ * Tracks multiple stacks of opcodes positions. This tracks a
+ * a table of "fingers" that point to various positions within
+ * a given opcode list. As each node is encountered, a set
+ * of fingers is pushed on the stack, that corresponds to
+ * the set of node tests that need to be done for that node.
+ * This is actually implemented as a stack of stacks of ints.
*/
public class UnionContext
{
- static final int MAXPATHS = 32;
- IntStack[] m_stacks = new IntStack[MAXPATHS];
- IntStack[] m_posStacks = new IntStack[MAXPATHS];
+ /**
+ * The initial number of columns in the table.
+ */
+ static final int INITIALTABLEWIDTH = 32;
+
+ /**
+ * The amount to increase the stack size by.
+ */
+ static final int BLOCKINCREASE = 32;
+
+ /**
+ * To avoid having to make a stack of objects, or multiple
+ * int stacks, each stack value is composed of multiple ints.
+ * In other words, if a step is pushed onto the stack, the
+ * top of the stack value will increase this amount.
+ */
+ static final int SLOTSPERVALUE = 3;
+
+ /**
+ * The position of the "finger" (i.e. the opcode position
+ * in the opcode map).
+ */
+ static final int SLOT_FINGER = 0;
+
+ /**
+ * The count for the given node, to be used for
+ * the position() function and the like.
+ */
+ static final int SLOT_COUNT = SLOT_FINGER+1;
+
+ /**
+ * The position for an int that can hold binary
+ * flags, for instance an axes flag for following::
+ * and descendents::.
+ */
+ static final int SLOT_FLAGS = SLOT_COUNT+1;
+
+ /**
+ * Flag to tell if the next step should walk children.
+ */
+ static final int FLAG_SHOULDWALKCHILDREN = (0x00000001 << 0);
+
+ /**
+ * Flag to tell if the next step should walk attributes.
+ */
+ static final int FLAG_SHOULDWALKATTRIBUTES = (0x00000001 << 1);
+
+ /**
+ * Flag to tell if the next step should walk following siblings.
+ */
+ static final int FLAG_SHOULDWALKFOLLOWINGSIBLINGS = (0x00000001 << 2);
+
+ /**
+ * This flag must be set down to the bottom of the stack. It tells
+ * that all following nodes must be tested.
+ */
+ static final int FLAG_SHOULDWALKFOLLOWING = (0x00000001 << 3);
+
+ IntStack[] m_stacks = new IntStack[INITIALTABLEWIDTH*SLOTSPERVALUE];
int m_stackCount;
- public static final int PSUEDO_POS_FOUNDNODE = -10000;
+ public static final int PSUEDO_POS_NULL = -10000;
public static final int PSUEDO_OP_FOUNDNODE = -10000;
/**
@@ -83,9 +144,9 @@
{
pushUnionPath(opMap, opPos);
}
- else if(XPath.OP_LOCATIONPATH == op)
+ else if(XPath.OP_LOCATIONPATH == (op & XPath.LOCATIONPATHEX_MASK))
{
- pushLocationPath(0, opMap, opPos);
+ pushLocationPath(opPos);
}
else
{
@@ -110,56 +171,125 @@
}
/**
+ * Get the size of the of the first stack, which should normally
+ * be the size of all the stacks, once construction of any
+ * given state is completed. If there are no stacks, return 0.
+ */
+ int size()
+ {
+ return (m_stackCount > 0) ? m_stacks[0].size() : 0;
+ }
+
+ /**
+ * Ensure there's enough room for the given index.
+ */
+ void ensureNewSpace(int number)
+ {
+ if((m_stackCount+number) >= m_stacks.length)
+ {
+ IntStack[] newStacks = new IntStack[m_stackCount+BLOCKINCREASE];
+ System.arraycopy(m_stacks, 0, newStacks, 0, m_stackCount);
+ }
+ }
+
+ /**
* Add a new stack and set the stack count
- * to which+1.
+ * to m_stackCount+1.
*/
- private final void addNewLocationPath(int which)
+ private int addNewLocationPath()
{
- m_stacks[which] = new IntStack();
- m_posStacks[which] = new IntStack();
- setLocationPathCount(which+1);
+ ensureNewSpace(1);
+ int pos = m_stackCount;
+ m_stackCount+=1;
+ m_stacks[pos] = new IntStack();
+ return pos;
+ }
+
+ /**
+ * Add a new stack and set the stack count
+ * to which+1, set the stack top to equal the
+ * other stack's tops+1, and copy opCodePos, nodePos, and flags
+ * down the stack.
+ * @return the position of the new stack.
+ */
+ int addNewLocationPath(int opCodePos, int nodePos, int flags)
+ {
+ int which = addNewLocationPath();
+ int depth = size();
+ IntStack stack = this.m_stacks[which];
+ for(int i = 0; i < depth; i += 3)
+ {
+ stack.addElement(opCodePos);
+ stack.addElement(nodePos);
+ stack.addElement(flags);
+ }
+ stack.addElement(opCodePos);
+ stack.addElement(nodePos);
+ stack.addElement(flags);
+ return which;
}
/**
- * Push the
+ * Add a new stack and set the stack count
+ * to which+1, set the stack top to equal the
+ * other stack's tops+1, copy opCodePos, nodePos, and flags
+ * down the stack, and copy topOpCodePos, topFlags, and
+ * topFlags to the top of the stack.
+ */
+ final int addNewLocationPath(int topOpCodePos, int topNodePos, int topFlags,
+ int opCodePos, int nodePos, int flags)
+ {
+ int which = addNewLocationPath();
+ int depth = size();
+ IntStack stack = this.m_stacks[which];
+ for(int i = 0; i < depth; i += 3)
+ {
+ stack.addElement(opCodePos);
+ stack.addElement(nodePos);
+ stack.addElement(flags);
+ }
+ stack.addElement(topOpCodePos);
+ stack.addElement(topNodePos);
+ stack.addElement(topFlags);
+ return which;
+ }
+
+ /**
+ * Add a new stack and set the stack count
+ * to which+1, set the stack top to equal the
+ * other stack's tops+1, copy opCodePos, nodePos, and flags
+ * down the stack, and copy topOpCodePos, topFlags, and
+ * topFlags to the top of the stack.
*/
- void pushLocationPath(int which, int[] opMap, int opPos)
+ final boolean setFlagsIfOpPos(int opCodePos, int flags)
{
- addNewLocationPath(which);
- opPos = XPath.getFirstChildPos(opPos);
- push(which, opPos, 1);
- /*
- while(opPos < posOfLastOp)
- {
- // step
- int stepType = xpath.m_opMap[opPos];
-
- switch(stepType)
+ int n = this.m_stackCount;
+ for(int i = 0; i < this.m_stackCount; i++)
+ {
+ IntStack stack=m_stacks[i];
+ int pos = (stack.size() - SLOTSPERVALUE)+SLOT_FINGER;
+ if(stack.elementAt(pos) == opCodePos)
{
- case xpath.FROM_ATTRIBUTES: // ?
- m_shouldWalkAttributes = true;
- case xpath.FROM_CHILDREN:
- case xpath.FROM_DESCENDANTS:
- break;
- case xpath.FROM_SELF:
- case xpath.FROM_DESCENDANTS_OR_SELF:
- // case xpath.FROM_FOLLOWING: ...might do these later
- // case xpath.FROM_FOLLOWING_SIBLINGS: ...might do these later
- break;
- default:
- System.out.println("ERROR! Should only find forward axes!");
+ pos = (stack.size() - SLOTSPERVALUE)+SLOT_FLAGS;
+ stack.setElementAt(flags, pos);
+ return true;
}
-
- opPos = XPath.getNextOpPos(opMap, opPos);
}
- if(xpath.m_opMap[opPos] != xpath.ENDOP)
- {
- System.out.println("ERROR! Could not find ENDOP after OP_LOCATIONPATH");
- }
- */
+ return false;
}
/**
+ * Push the a new location path
+ */
+ int pushLocationPath(int opPos)
+ {
+ int which = addNewLocationPath();
+ opPos = XPath.getFirstChildPos(opPos);
+ push(which, opPos, 0 /* start count */, 0 /*flags */);
+ return which;
+ }
+
+ /**
* Walk a union pattern and push each of the positions
* of the first child of the location steps.
*/
@@ -167,39 +297,207 @@
{
opPos+=2;
- for(int i = 0; opMap[opPos] == XPath.OP_LOCATIONPATH; i++)
+ for(int i = 0;
+ (opMap[opPos] & XPath.LOCATIONPATHEX_MASK) == XPath.OP_LOCATIONPATH; i++)
{
int nextOpPos = XPath.getNextOpPos(opMap, opPos);
- pushLocationPath(i, opMap, opPos);
+ pushLocationPath(opPos);
opPos = nextOpPos;
}
}
/**
- * Set the index position for a node, associated with
- * the given LocationPath.
+ * Set the given flag which is associated with a traversal
+ * from the tested node.
*/
- void setNodePosition(int which, int nodePos)
+ void setOpPos(int which, int finger)
{
- m_posStacks[which].setTop(nodePos);
+ IntStack stack=m_stacks[which];
+ int pos = (stack.size() - SLOTSPERVALUE)+SLOT_FINGER;
+ stack.setElementAt(finger, pos);
}
+
+ /**
+ * Set the given flag which is associated with a traversal
+ * from the tested node.
+ */
+ void setFlags(int which, int flag)
+ {
+ IntStack stack=m_stacks[which];
+ int pos = (stack.size() - SLOTSPERVALUE)+SLOT_FLAGS;
+ stack.setElementAt(flag, pos);
+ }
+
+ /**
+ * Set the given flag(s) which are associated with a traversal
+ * from the tested node.
+ */
+ void clearFlags(int which, int flag)
+ {
+ IntStack stack=m_stacks[which];
+ int sz = stack.size();
+ int pos = (sz - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = stack.elementAt(pos) + 1;
+ m_stacks[which].setElementAt(flags&(~flag), pos);
+ }
+
+ /**
+ * Clear all given flag(s) which are associated with a traversal
+ * from the tested node.
+ */
+ void clearAllFlags(int flag)
+ {
+ for(int i = 0; i < m_stackCount; i++)
+ {
+ clearFlags(i, flag);
+ }
+ }
+
+ /**
+ * Add the given flag which is associated with a traversal
+ * from the tested node.
+ */
+ void addFlag(int which, int flag)
+ {
+ IntStack stack=m_stacks[which];
+ int sz = stack.size();
+ int pos = (sz - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = stack.elementAt(pos) + 1;
+ m_stacks[which].setElementAt(flags|flag, pos);
+ }
+
+ /**
+ * For the given location path stack, add a
+ * flag to the bottom of the stack. This is
+ * used for FOLLOWING traversal.
+ */
+ void addFlagToBottom(int which, int flag)
+ {
+ IntStack stack=m_stacks[which];
+ int sz = stack.size();
+
+ for(int i = sz; i > 0; i-=SLOTSPERVALUE)
+ {
+ int pos = (i - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = stack.elementAt(pos) + 1;
+ m_stacks[which].setElementAt(flags|flag, pos);
+ }
+ }
+
+ /**
+ * Test the given flag which is associated with a traversal
+ * from the tested node.
+ */
+ boolean testFlag(int which, int flag)
+ {
+ IntStack stack=m_stacks[which];
+ int sz = stack.size();
+ int pos = (sz - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = stack.elementAt(pos) + 1;
+ return (flags & flag) != 0;
+ }
+
+ /**
+ * Test the given flag across the stacks which are associated with a traversal
+ * from the tested node.
+ */
+ boolean testUnionFlags(int flag)
+ {
+ for(int i = 0; i < m_stackCount; i++)
+ {
+ if(testFlag(i, flag))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Test the given flag across the stacks which are associated with a traversal
+ * from the tested node.
+ */
+ int getUnionFlags(int filter)
+ {
+ int stackTopFlagsPos = (size() - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = 0x00000000;
+ for(int i = 0; i < m_stackCount; i++)
+ {
+ IntStack stack=m_stacks[i];
+ flags |= stack.elementAt(stackTopFlagsPos) & filter;
+ }
+ return flags;
+ }
+
+ /**
+ * Test the given flag across the stacks which are associated with a traversal
+ * from the tested node.
+ */
+ int getUnionFlags()
+ {
+ int stackTopFlagsPos = (size() - SLOTSPERVALUE)+SLOT_FLAGS;
+ int flags = 0x00000000;
+ int c = m_stackCount;
+ for(int i = 0; i < c; i++)
+ flags |= m_stacks[i].m_map[stackTopFlagsPos];
+ return flags;
+ }
+
/**
* Set the index position for a node, associated with
* the given LocationPath.
*/
- void incrementNodePosition(int which)
+ void setNodeCount(int which, int nodePos)
{
- m_posStacks[which].setTop(getNodePosition(which)+1);
+ IntStack stack=m_stacks[which];
+ int pos = (stack.size() - SLOTSPERVALUE)+SLOT_COUNT;
+ stack.setElementAt(nodePos, pos);
}
/**
- * Set the index position for a node, associated with
+ * Set the found count for a node, associated with
+ * the given LocationPath. The count is copied down
+ * the stack 'till the finger (op code position)
+ * changes.
+ */
+ void incrementNodeCount(int which)
+ {
+ IntStack stack=m_stacks[which];
+ int sz = stack.size();
+ int pos = (sz - SLOTSPERVALUE)+SLOT_COUNT;
+ int finger = (sz - SLOTSPERVALUE)+SLOT_FINGER;
+ int count = stack.elementAt(pos) + 1;
+ m_stacks[which].setElementAt(count, pos);
+ for(int i = (sz-SLOTSPERVALUE); i >= SLOTSPERVALUE; i -= SLOTSPERVALUE)
+ {
+ int nextfinger = (i - SLOTSPERVALUE)+SLOT_FINGER;
+ if(nextfinger == finger)
+ m_stacks[which].setElementAt(count, i);
+ else
+ break;
+ }
+ }
+
+ /**
+ * Get the index position for a node, associated with
* the given LocationPath.
*/
- int getNodePosition(int which)
+ int getNodeCount(int which)
{
- return m_posStacks[which].peek();
+ if(m_stackCount > 0)
+ {
+ IntStack stack=m_stacks[which];
+ int depth = stack.size();
+ if(depth > 0)
+ {
+ int pos = (depth - SLOTSPERVALUE)+SLOT_COUNT;
+ int nodePos = stack.elementAt(pos);
+ return nodePos;
+ }
+ else
+ return 0;
+ }
+ else
+ return 0;
}
/**
@@ -209,10 +507,13 @@
* @param opCodePos an opcode position.
* @return the <code>opCodePos</code> argument.
*/
- public int push(int which, int opCodePos, int nodePos)
+ public int push(int which, int opCodePos, int nodePos, int flags)
{
- m_posStacks[which].push(nodePos);
- return m_stacks[which].push(opCodePos);
+ IntStack stack=m_stacks[which];
+ int returnVal = stack.push(opCodePos);
+ stack.push(nodePos);
+ stack.push(flags);
+ return returnVal;
}
/**
@@ -225,8 +526,11 @@
*/
public int pop(int which)
{
- m_posStacks[which].pop();
- return m_stacks[which].pop();
+ IntStack stack=m_stacks[which];
+ // Could be optimized.
+ int i = stack.peek();
+ stack.quickPop(SLOTSPERVALUE);
+ return i;
}
/**
* Pop all stacks by one.
*
@@ -237,7 +541,7 @@
int n = m_stackCount;
for(int i = 0; i < n; i++)
{
- pop(i);
+ m_stacks[i].quickPop(SLOTSPERVALUE);
}
}
@@ -251,7 +555,11 @@
*/
public int peek(int which)
{
- return m_stacks[which].peek();
+ IntStack stack=m_stacks[which];
+ int depth = stack.size();
+ int pos = (depth - SLOTSPERVALUE)+SLOT_FINGER;
+ int finger = stack.elementAt(pos);
+ return finger;
}
/**
@@ -281,5 +589,47 @@
return false;
}
return true;
- }
+ }
/**
+ * Write a diagnostic dump of the stacks to the console.
+ */
void writeDiagnostics(int nodeID, java.io.PrintWriter pw)
+ throws java.io.IOException
{
+ int depth = size();
+ java.text.DecimalFormat formatter
+ = (java.text.DecimalFormat)java.text.NumberFormat.getNumberInstance();
+ formatter.applyPattern("0000");
+ pw.println("************************");
+ System.out.println("************************");
+ pw.println("****** NODE# "+formatter.format(nodeID)+" ******");
+ System.out.println("****** NODE# "+formatter.format(nodeID)+" ******");
+ pw.println("op count flags");
System.out.println("op count flags");
int rows=depth/3;
+ for(int i = (depth-this.SLOTSPERVALUE), l = (rows-1); i >= 0; i-=this.SLOTSPERVALUE, l--)
+ {
+ pw.println("------ level "+formatter.format(l)+" ------");
+ System.out.println("------ level "+formatter.format(l)+" ------");
+ for(int k = 0; k < m_stackCount; k++)
+ {
+ if(0 != k)
{
+ pw.print(" | ");
+ System.out.print(" | ");
+ }
IntStack stack=m_stacks[k];
+ pw.print(formatter.format(stack.elementAt(i+this.SLOT_FINGER))
+ +", "+formatter.format(stack.elementAt(i+this.SLOT_COUNT)));
+ System.out.print(formatter.format(stack.elementAt(i+this.SLOT_FINGER))
+ +", "+formatter.format(stack.elementAt(i+this.SLOT_COUNT)));
+ int flags = stack.elementAt(i+this.SLOT_FLAGS);
pw.print(", (");
+ System.out.print(", (");
+ pw.print((0 !=(flags & FLAG_SHOULDWALKCHILDREN)) ? "C " : "X ");
+ System.out.print((0 !=(flags & FLAG_SHOULDWALKCHILDREN)) ? "C " : "X ");
+ pw.print((0 !=(flags & FLAG_SHOULDWALKATTRIBUTES)) ? "A " : "X ");
+ System.out.print((0 !=(flags & FLAG_SHOULDWALKATTRIBUTES)) ? "A " : "X ");
+ pw.print((0 !=(flags & FLAG_SHOULDWALKFOLLOWINGSIBLINGS)) ? "FS" : "X ");
+ System.out.print((0 !=(flags & FLAG_SHOULDWALKFOLLOWINGSIBLINGS)) ? "FS" : "X ");
+ boolean shouldWalkAttributes = (0 !=(flags & FLAG_SHOULDWALKATTRIBUTES));
+ boolean shouldWalkFollowingSiblings = (0 !=(flags & FLAG_SHOULDWALKFOLLOWINGSIBLINGS));
+ pw.print(")");
+ System.out.print(")");
if(k == (m_stackCount-1))
+ {
pw.println();
System.out.println();
}
+ }
+ }
pw.println("--- #rows "+formatter.format(rows)+" ---");
System.out.println("--- #rows "+formatter.format(rows)+" ---");
pw.println("--- #columns "+formatter.format(m_stackCount)+" ---");
System.out.println("--- #columns "+formatter.format(m_stackCount)+" ---");
+ pw.flush();
}
}
1.5 +12 -2 xml-xalan/src/org/apache/xalan/xpath/XLocator.java
Index: XLocator.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/XLocator.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- XLocator.java 1999/12/13 07:52:10 1.4
+++ XLocator.java 2000/02/13 16:42:41 1.5
@@ -92,11 +92,15 @@
* Execute a union. The union of its operands, which are locationPaths,
* must be node-sets.
* @param xpath The xpath that is executing.
+ * @param execContext The execution context.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
* @returns the result of the query in an XNodeSet object.
*/
- XNodeSet union(XPath xpath, XPathSupport execContext, Node context, int opPos)
+ XNodeSet union(XPath xpath, XPathSupport execContext, Node context,
+ int opPos, NodeCallback callback, Object callbackInfo)
throws org.xml.sax.SAXException;
/**
@@ -108,9 +112,15 @@
* @param xpath The xpath that is executing.
* @param context The current source tree context node.
* @param opPos The current position in the xpath.m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
+ * @param stopAtFirst True if only the first found node in doc order is needed.
* @returns the result of the query in an XNodeSet object.
*/
- XNodeSet locationPath(XPath xpath, XPathSupport execContext, Node context, int opPos)
+ XNodeSet locationPath(XPath xpath, XPathSupport execContext,
+ Node context, int opPos,
+ NodeCallback callback, Object callbackInfo,
+ boolean stopAtFirst)
throws org.xml.sax.SAXException;
/**
1.15 +320 -248 xml-xalan/src/org/apache/xalan/xpath/XPath.java
Index: XPath.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPath.java,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- XPath.java 2000/02/09 20:11:11 1.14
+++ XPath.java 2000/02/13 16:42:41 1.15
@@ -55,7 +55,7 @@
* <http://www.apache.org/>.
*/
package org.apache.xalan.xpath;
-
+
import org.w3c.dom.*;
import java.util.*;
import org.apache.xalan.xpath.xml.PrefixResolver;
@@ -64,7 +64,7 @@
import org.apache.xalan.xpath.res.XPATHErrorResources;
import org.apache.xalan.xpath.xml.XSLMessages;
import org.apache.xalan.xpath.xml.ProblemListener;
-
+
/**
* The XPath class represents the semantic parse tree of the XPath pattern.
* It is the representation of the grammar which filters out
@@ -216,7 +216,7 @@
throw new RuntimeException("In XPath.readObject: "+cnfe.getMessage());
}
}
-
+
/**
* Given an expression and a context, return the result.
* @param expression The expression.
@@ -229,6 +229,27 @@
public XObject execute(XPathSupport execContext, Node contextNode,
PrefixResolver namespaceContext)
throws org.xml.sax.SAXException
+ {
+ return execute(execContext, contextNode, namespaceContext, null, null, false);
+ }
+
+ /**
+ * Given an expression and a context, return the result.
+ * @param execContext The execution context.
+ * @param contextNode The node that "." expresses.
+ * @param namespaceContext The context in which namespaces in the
+ * queries are supposed to be expanded.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
+ * @param stopAtFirst True if the search should stop once the first node in document
+ * order is found.
+ * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
+ * the error condition is severe enough to halt processing.
+ */
+ public XObject execute(XPathSupport execContext, Node contextNode,
+ PrefixResolver namespaceContext,
+ NodeCallback callback, Object callbackInfo, boolean stopAtFirst)
+ throws org.xml.sax.SAXException
{
PrefixResolver savedPrefixResolver = execContext.getNamespaceContext();
execContext.setNamespaceContext(namespaceContext);
@@ -236,7 +257,11 @@
XObject xobj = null;
try
{
- xobj = execute(execContext, contextNode, 0);
+ if(null != callbackInfo)
+ execContext.pushXPathContext(this, execContext, contextNode, namespaceContext);
+ xobj = execute(execContext, contextNode, 0, callback, callbackInfo, stopAtFirst);
+ if(null != callbackInfo)
+ execContext.popXPathContext();
}
finally
{
@@ -286,62 +311,32 @@
return score;
}
-
- /**
- * Get the match score of the given node index.
- * @param context The current source tree context node.
- * @returns score, one of MATCH_SCORE_NODETEST,
- * MATCH_SCORE_NONE, MATCH_SCORE_OTHER, MATCH_SCORE_QNAME.
- */
- public double getMatchScore(XPathSupport execContext, org.apache.xalan.xpath.dtm.DTM dtm, int context)
- throws org.xml.sax.SAXException
- {
- double score = MATCH_SCORE_NONE;
- int opPos = 0;
- if(m_opMap[opPos] == OP_MATCHPATTERN)
- {
- opPos = getFirstChildPos(opPos);
-
- XLocator locator = execContext.getXLocatorFromNode(dtm.getDocument());
-
- if(null == locator)
- locator = execContext.createXLocatorHandler();
-
- org.apache.xalan.xpath.dtm.DTMNodeLocator dtmLocator
- = (org.apache.xalan.xpath.dtm.DTMNodeLocator)locator;
-
- while(m_opMap[opPos] == OP_LOCATIONPATHPATTERN)
- {
- int nextOpPos = getNextOpPos(opPos);
-
- // opPos = getFirstChildPos(opPos);
- score = dtmLocator.locationPathPattern(this, execContext, dtm, context, opPos);
- if(score != MATCH_SCORE_NONE)
- break;
- opPos = nextOpPos;
- }
-
- }
- else
- {
- error(dtm.getNode( context ), XPATHErrorResources.ER_EXPECTED_MATCH_PATTERN); //"Expected match pattern in getMatchScore!");
- }
- return score;
- }
-
/**
* Get the position in the current context node list.
*/
- int getCountOfContextNodeList(XPathSupport execContext)
+ int getCountOfContextNodeList(XPath path, XPathSupport execContext, Node context)
+ throws org.xml.sax.SAXException
{
-// assert(null != m_contextNodeList, "m_contextNodeList must be non-null");
+ // assert(null != m_contextNodeList, "m_contextNodeList must be non-null");
if(execContext.getThrowFoundIndex())
throw new FoundIndex();
- return execContext.getContextNodeList().getLength();
+ NodeList cnl = execContext.getContextNodeList();
+
+ if(null == cnl)
+ {
+ XObject xobject = execContext.reExecuteXPathContext(path, execContext, context);
+ if((null != xobject) && (xobject.getType() == XObject.CLASS_NODESET))
+ cnl = xobject.nodeset();
+ else if(execContext.getContextNodePosition() > 0)
+ throw new FoundIndex(); // Tell 'em to try again!
+ else
+ return 0; // I give up...
+ }
+ return cnl.getLength();
}
/**
@@ -353,8 +348,12 @@
if(execContext.getThrowFoundIndex())
throw new FoundIndex();
+
+ int pos = execContext.getContextNodePosition();
+ if(pos >= 0)
+ return pos;
- int pos = -1;
+ pos = -1;
if(null != execContext.getContextNodeList())
{
@@ -799,9 +798,13 @@
* Computes the union of its operands which must be node-sets.
* @param context The current source tree context node.
* @param opPos The current position in the m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
* @returns the union of node-set operands.
*/
- protected XNodeSet union(XPathSupport execContext, Node context, int opPos)
+ protected XNodeSet union(XPathSupport execContext,
+ Node context, int opPos,
+ NodeCallback callback, Object callbackInfo)
throws org.xml.sax.SAXException
{
XLocator xlocator = execContext.getXLocatorFromNode(context);
@@ -809,7 +812,8 @@
if(null == xlocator)
xlocator = execContext.createXLocatorHandler();
- XNodeSet results = xlocator.union(this, execContext, context, opPos);
+ XNodeSet results = xlocator.union(this, execContext,
+ context, opPos, callback, callbackInfo);
return results;
}
@@ -919,9 +923,14 @@
* Execute a location path.
* @param context The current source tree context node.
* @param opPos The current position in the m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
* @returns a node-set.
*/
- public XNodeSet locationPath(XPathSupport execContext, Node context, int opPos)
+ public XNodeSet locationPath(XPathSupport execContext,
+ Node context, int opPos,
+ NodeCallback callback, Object callbackInfo,
+ boolean stopAtFirst)
throws org.xml.sax.SAXException
{
XLocator xlocator = execContext.getXLocatorFromNode(context);
@@ -929,7 +938,9 @@
if(null == xlocator)
xlocator = execContext.createXLocatorHandler();
- XNodeSet results = xlocator.locationPath(this, execContext, context, opPos);
+ XNodeSet results = xlocator.locationPath(this, execContext,
+ context, opPos, callback, callbackInfo,
+ stopAtFirst);
return results;
}
@@ -943,7 +954,7 @@
public XObject predicate(XPathSupport execContext, Node context, int opPos)
throws org.xml.sax.SAXException
{
- XObject expr1 = execute(execContext, context, opPos+2);
+ XObject expr1 = execute(execContext, context, opPos+2, null, null, true);
int objType = expr1.getType();
if((XObject.CLASS_NUMBER != objType) && (XObject.CLASS_BOOLEAN != objType))
{
@@ -1026,9 +1037,9 @@
opPos = getNextOpPos(opPos);
XNodeSet mnl = null;
if((opPos < m_opMap[MAPINDEX_LENGTH]) &&
- (OP_LOCATIONPATH == m_opMap[opPos]))
+ (OP_LOCATIONPATH == (m_opMap[opPos] & XPath.LOCATIONPATHEX_MASK)))
{
- mnl = locationPath(execContext, (Node)val, opPos);
+ mnl = locationPath(execContext, (Node)val, opPos, null, null, false);
}
result = (null == mnl) ? new XNodeSet((Node)val)
: mnl;
@@ -1039,13 +1050,13 @@
opPos = getNextOpPos(opPos);
XNodeSet mnl = null;
if((opPos < m_opMap[MAPINDEX_LENGTH]) &&
- (OP_LOCATIONPATH == m_opMap[opPos]))
+ (OP_LOCATIONPATH == (m_opMap[opPos] & XPath.LOCATIONPATHEX_MASK)))
{
NodeList nl = (NodeList)val;
int nNodes = nl.getLength();
for(int i = 0; i < nNodes; i++)
{
- XNodeSet xnl = locationPath(execContext, nl.item(i), opPos);
+ XNodeSet xnl = locationPath(execContext, nl.item(i), opPos, null, null, false);
if(null == xnl)
mnl = xnl;
else
@@ -1212,202 +1223,235 @@
}
return targetStrings;
}
+
+ /**
+ * Execute the XPath object.
+ * @param execContext The execution context.
+ * @param context The current source tree context node.
+ * @param opPos The current position in the xpath.m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
+ * @return The result of the XPath.
+ */
+ public XObject execute(XPathSupport execContext,
+ Node context, int opPos)
+ throws org.xml.sax.SAXException
+ {
+ return execute(execContext, context, opPos, null, null, false);
+ }
- public XObject execute(XPathSupport execContext, Node context, int opPos)
+ /**
+ * Execute the XPath object.
+ * @param execContext The execution context.
+ * @param context The current source tree context node.
+ * @param opPos The current position in the xpath.m_opMap array.
+ * @param callback Interface that implements the processLocatedNode method.
+ * @param callbackInfo Object that will be passed to the processLocatedNode method.
+ * @return The result of the XPath.
+ */
+ public XObject execute(XPathSupport execContext,
+ Node context, int opPos,
+ NodeCallback callback, Object callbackInfo, boolean stopAtFirst)
throws org.xml.sax.SAXException
{
XObject result = null;
- switch(m_opMap[opPos])
+ boolean doLoop = true;
+ while(doLoop)
{
- case OP_XPATH:
- result = execute(execContext, context, opPos+2);
- break;
- case OP_MATCHPATTERN:
- result = matchPattern(execContext, context, opPos+2);
- break;
- case EMPTY:
- opPos++;
- break;
- case OP_OR:
- result = or(execContext, context, opPos);
- break;
- case OP_AND:
- result = and(execContext, context, opPos);
- break;
- case OP_NOTEQUALS:
- result = notequals(execContext, context, opPos);
- break;
- case OP_EQUALS:
- result = equals(execContext, context, opPos);
- break;
- case OP_LTE:
- result = lte(execContext, context, opPos);
- break;
- case OP_LT:
- result = lt(execContext, context, opPos);
- break;
- case OP_GTE:
- result = gte(execContext, context, opPos);
- break;
- case OP_GT:
- result = gt(execContext, context, opPos);
- break;
- case OP_PLUS:
- result = plus(execContext, context, opPos);
- break;
- case OP_MINUS:
- result = minus(execContext, context, opPos);
- break;
- case OP_MULT:
- result = mult(execContext, context, opPos);
- break;
- case OP_DIV:
- result = div(execContext, context, opPos);
- break;
- case OP_MOD:
- result = mod(execContext, context, opPos);
- break;
- case OP_QUO:
- result = quo(execContext, context, opPos);
- break;
- case OP_NEG:
- result = neg(execContext, context, opPos);
- break;
- case OP_STRING:
- result = string(execContext, context, opPos);
- break;
- case OP_BOOL:
- result = bool(execContext, context, opPos);
- break;
- case OP_NUMBER:
- result = number(execContext, context, opPos);
- break;
- case OP_UNION:
- result = union(execContext, context, opPos);
- break;
- case OP_LITERAL:
- result = literal(execContext, context, opPos);
- break;
- case OP_VARIABLE:
- result = variable(execContext, context, opPos);
- break;
- case OP_GROUP:
- result = group(execContext, context, opPos);
- break;
- case OP_NUMBERLIT:
- result = numberlit(execContext, context, opPos);
- break;
- case OP_ARGUMENT:
- result = arg(execContext, context, opPos);
- break;
- case OP_EXTFUNCTION:
- {
- int endExtFunc = opPos+m_opMap[opPos+1]-1;
- opPos = getFirstChildPos(opPos);
- String ns = (String)m_tokenQueue[m_opMap[opPos]];
- opPos++;
- String funcName = (String)m_tokenQueue[m_opMap[opPos]];
- opPos++;
- Vector args = new Vector();
- while(opPos < endExtFunc)
- {
- int nextOpPos = getNextOpPos(opPos);
- args.addElement( execute(execContext, context, opPos) );
- opPos = nextOpPos;
- }
- result = extfunction(execContext, context, opPos, ns, funcName, args);
- }
- break;
- case OP_FUNCTION:
+ switch(m_opMap[opPos])
{
- int endFunc = opPos+m_opMap[opPos+1]-1;
- opPos = getFirstChildPos(opPos);
- int funcID = m_opMap[opPos];
- opPos++;
- Vector args = new Vector();
- while(opPos < endFunc)
- {
- int nextOpPos = getNextOpPos(opPos);
- args.addElement(execute(execContext, context, opPos));
- opPos = nextOpPos;
- }
- if(-1 != funcID)
- {
- result = function(execContext, context, opPos, funcID, args);
- }
- else
- {
- warn(XPATHErrorResources.WG_FUNCTION_TOKEN_NOT_FOUND); //"function token not found.");
- }
+ case OP_XPATH:
+ opPos+=2;
+ continue;
+ case OP_MATCHPATTERN:
+ result = matchPattern(execContext, context, opPos+2);
+ break;
+ case EMPTY:
+ opPos++;
+ break;
+ case OP_OR:
+ result = or(execContext, context, opPos);
+ break;
+ case OP_AND:
+ result = and(execContext, context, opPos);
+ break;
+ case OP_NOTEQUALS:
+ result = notequals(execContext, context, opPos);
+ break;
+ case OP_EQUALS:
+ result = equals(execContext, context, opPos);
+ break;
+ case OP_LTE:
+ result = lte(execContext, context, opPos);
+ break;
+ case OP_LT:
+ result = lt(execContext, context, opPos);
+ break;
+ case OP_GTE:
+ result = gte(execContext, context, opPos);
+ break;
+ case OP_GT:
+ result = gt(execContext, context, opPos);
+ break;
+ case OP_PLUS:
+ result = plus(execContext, context, opPos);
+ break;
+ case OP_MINUS:
+ result = minus(execContext, context, opPos);
+ break;
+ case OP_MULT:
+ result = mult(execContext, context, opPos);
+ break;
+ case OP_DIV:
+ result = div(execContext, context, opPos);
+ break;
+ case OP_MOD:
+ result = mod(execContext, context, opPos);
+ break;
+ case OP_QUO:
+ result = quo(execContext, context, opPos);
+ break;
+ case OP_NEG:
+ result = neg(execContext, context, opPos);
+ break;
+ case OP_STRING:
+ result = string(execContext, context, opPos);
+ break;
+ case OP_BOOL:
+ result = bool(execContext, context, opPos);
+ break;
+ case OP_NUMBER:
+ result = number(execContext, context, opPos);
+ break;
+ case OP_UNION:
+ result = union(execContext, context, opPos, callback, callbackInfo);
+ break;
+ case OP_LITERAL:
+ result = literal(execContext, context, opPos);
+ break;
+ case OP_VARIABLE:
+ result = variable(execContext, context, opPos);
+ break;
+ case OP_GROUP:
+ result = group(execContext, context, opPos);
+ break;
+ case OP_NUMBERLIT:
+ result = numberlit(execContext, context, opPos);
+ break;
+ case OP_ARGUMENT:
+ result = arg(execContext, context, opPos);
+ break;
+ case OP_EXTFUNCTION:
+ {
+ int endExtFunc = opPos+m_opMap[opPos+1]-1;
+ opPos = getFirstChildPos(opPos);
+ String ns = (String)m_tokenQueue[m_opMap[opPos]];
+ opPos++;
+ String funcName = (String)m_tokenQueue[m_opMap[opPos]];
+ opPos++;
+ Vector args = new Vector();
+ while(opPos < endExtFunc)
+ {
+ int nextOpPos = getNextOpPos(opPos);
+ args.addElement( execute(execContext, context, opPos) );
+ opPos = nextOpPos;
+ }
+ result = extfunction(execContext, context, opPos, ns, funcName, args);
+ }
+ break;
+ case OP_FUNCTION:
+ {
+ int endFunc = opPos+m_opMap[opPos+1]-1;
+ opPos = getFirstChildPos(opPos);
+ int funcID = m_opMap[opPos];
+ opPos++;
+ Vector args = new Vector();
+ while(opPos < endFunc)
+ {
+ int nextOpPos = getNextOpPos(opPos);
+ args.addElement(execute(execContext, context, opPos));
+ opPos = nextOpPos;
+ }
+ if(-1 != funcID)
+ {
+ result = function(execContext, context, opPos, funcID, args);
+ }
+ else
+ {
+ warn(XPATHErrorResources.WG_FUNCTION_TOKEN_NOT_FOUND); //"function token not found.");
+ }
+ }
+ break;
+ case OP_LOCATIONPATH_EX:
+ case OP_LOCATIONPATH:
+ result = locationPath(execContext, context, opPos, callback, callbackInfo, stopAtFirst);
+ break;
+ case OP_LOCATIONPATHPATTERN:
+ result = locationPathPattern(execContext, context, opPos);
+ break;
+ /*
+ case OP_PREDICATE:
+ break;
+ case FROM_ANCESTORS:
+ break;
+ case FROM_ANCESTORS_OR_SELF:
+ break;
+ case FROM_ATTRIBUTES:
+ break;
+ case FROM_CHILDREN:
+ break;
+ case FROM_DESCENDANTS:
+ break;
+ case FROM_DESCENDANTS_OR_SELF:
+ break;
+ case FROM_FOLLOWING:
+ break;
+ case FROM_FOLLOWING_SIBLINGS:
+ break;
+ case FROM_PARENT:
+ break;
+ case FROM_PRECEDING:
+ break;
+ case FROM_PRECEDING_SIBLINGS:
+ break;
+ case FROM_SELF:
+ break;
+ case FROM_NAMESPACE:
+ break;
+ // case FROM_ATTRIBUTE:
+ // break;
+ // case FROM_DOC:
+ // break;
+ // case FROM_DOCREF:
+ // break;
+ // case FROM_ID:
+ // break;
+ // case FROM_IDREF:
+ // break;
+ case FROM_ROOT:
+ break;
+ case NODETYPE_COMMENT:
+ break;
+ case NODETYPE_TEXT:
+ break;
+ case NODETYPE_PI:
+ break;
+ case NODETYPE_NODE:
+ break;
+ case NODETYPE_ROOT:
+ break;
+ case NODETYPE_ANYELEMENT:
+ break;
+ case NODENAME:
+ break;
+ */
+ default:
+ error(context, XPATHErrorResources.ER_UNKNOWN_OPCODE, new Object[] {Integer.toString(m_opMap[opPos])}); //"ERROR! Unknown op code: "+m_opMap[opPos]);
}
- break;
- case OP_LOCATIONPATH:
- result = locationPath(execContext, context, opPos);
- break;
- case OP_LOCATIONPATHPATTERN:
- result = locationPathPattern(execContext, context, opPos);
- break;
- /*
- case OP_PREDICATE:
- break;
- case FROM_ANCESTORS:
- break;
- case FROM_ANCESTORS_OR_SELF:
- break;
- case FROM_ATTRIBUTES:
- break;
- case FROM_CHILDREN:
- break;
- case FROM_DESCENDANTS:
- break;
- case FROM_DESCENDANTS_OR_SELF:
- break;
- case FROM_FOLLOWING:
- break;
- case FROM_FOLLOWING_SIBLINGS:
- break;
- case FROM_PARENT:
- break;
- case FROM_PRECEDING:
- break;
- case FROM_PRECEDING_SIBLINGS:
- break;
- case FROM_SELF:
- break;
- case FROM_NAMESPACE:
- break;
- // case FROM_ATTRIBUTE:
- // break;
- // case FROM_DOC:
- // break;
- // case FROM_DOCREF:
- // break;
- // case FROM_ID:
- // break;
- // case FROM_IDREF:
- // break;
- case FROM_ROOT:
- break;
- case NODETYPE_COMMENT:
- break;
- case NODETYPE_TEXT:
- break;
- case NODETYPE_PI:
- break;
- case NODETYPE_NODE:
- break;
- case NODETYPE_ROOT:
- break;
- case NODETYPE_ANYELEMENT:
- break;
- case NODENAME:
- break;
- */
- default:
- error(context, XPATHErrorResources.ER_UNKNOWN_OPCODE, new Object[] {Integer.toString(m_opMap[opPos])}); //"ERROR! Unknown op code: "+m_opMap[opPos]);
- }
- return result;
+ doLoop = false;
}
+ return result;
+}
// ============= Op Code Position Helper Functions =================
private void ____OPCODE_POSITION_HELPER_FUNCTIONS____(){}
@@ -1941,6 +1985,9 @@
* XNodeSet
*/
public static final int OP_LOCATIONPATH = 28;
+ public static final int LOCATIONPATHEX_MASK = 0xFFFF0000;
+ public static final int LOCATIONPATHEX_ISSIMPLE = 0x00010000;
+ public static final int OP_LOCATIONPATH_EX = (28 | 0x00010000);
/**
@@ -2248,5 +2295,30 @@
* The number of elements that m_patternMap maps;
*/
public int m_patternMapSize;
+
+ //====================
+ /*
+ public static void main( String argv[] )
+ {
+ TransformFactory sfactory = XSLTFactory.newTransformFactory(...);
+ Params params = new Params(); // Bag of params..
+ params.set("foo", "http://foo.com", "hello");
+
+ Transform transform1 = sfactory .newTransform(new InputSource("t1.xsl"));
+ XSLTProcessor processor1 = transform1.newProcessor();
+
+ Transform transform2= sfactory.newTransform(new InputSource("t2.xsl"));
+ XSLTProcessor processor2 = transform2.newProcessor();
+
+ Transform transform3 = sfactory.newTransform(new InputSource("t3.xsl"));
+ XSLTProcessor processor3= transform3 .newProcessor();
+
+ processor3.setResultTarget(new Result(System.out));
+ processor2.setResultTarget(new Result(processor3));
+ processor1.process(new InputSource("foo.xml"), params, new Result(processor2));
+ }
+ */
+//====================
+
}
1.17 +80 -1 xml-xalan/src/org/apache/xalan/xpath/XPathProcessorImpl.java
Index: XPathProcessorImpl.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPathProcessorImpl.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- XPathProcessorImpl.java 2000/02/09 20:11:11 1.16
+++ XPathProcessorImpl.java 2000/02/13 16:42:41 1.17
@@ -187,8 +187,16 @@
}
error(XPATHErrorResources.ER_EXTRA_ILLEGAL_TOKENS, new Object[] {extraTokens}); //"Extra illegal tokens: "+extraTokens);
}
-
+ pathObj.shrink();
+ doStaticAnalysis(pathObj);
}
+
+ /**
+ * Analyze the XPath object to give optimization information.
+ */
+ void doStaticAnalysis(XPath pathObj)
+ {
+ }
/**
* Given an string, make an XPath object, on order that a parse doesn't
@@ -219,6 +227,7 @@
// Terminate for safety.
m_xpath.m_opMap[m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH]] = m_xpath.ENDOP;
m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] += 1;
+ m_xpath.shrink();
}
// Lexical Analysis
@@ -1747,7 +1756,60 @@
while(continueOrLoop);
m_xpath.m_opMap[opPos + m_xpath.MAPINDEX_LENGTH] = m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] - opPos;
}
+
+ /**
+ * Analyze a union pattern and tell if the axes are
+ * all descendants.
+ * (Move to XPath?)
+ */
+ static boolean isLocationPathSimpleFollowing(XPath xpath, int opPos)
+ {
+ int posOfLastOp = xpath.getNextOpPos(opPos)-1;
+
+ opPos = xpath.getFirstChildPos(opPos);
+ // step
+ int stepType = xpath.m_opMap[opPos];
+
+ // make sure all step types are going forwards
+ switch(stepType)
+ {
+ case XPath.FROM_SELF:
+ case XPath.FROM_ATTRIBUTES:
+ case XPath.FROM_CHILDREN:
+ case XPath.FROM_DESCENDANTS:
+ case XPath.FROM_DESCENDANTS_OR_SELF:
+ case XPath.FROM_FOLLOWING:
+ case XPath.FROM_FOLLOWING_SIBLINGS:
+ if(xpath.m_opMap[xpath.getNextOpPos(opPos)] == xpath.ENDOP)
+ {
+ // Add the length of the step itself, plus the length of the op,
+ // and two length arguments, to the op position.
+ opPos = (xpath.getArgLengthOfStep(opPos)+xpath.getFirstChildPosOfStep(opPos));
+ int nextStepType = xpath.m_opMap[opPos];
+
+ if(xpath.OP_PREDICATE == nextStepType)
+ {
+ int firstPredPos = opPos+2;
+ int predicateType = xpath.m_opMap[firstPredPos];
+ if((XPath.OP_NUMBERLIT == predicateType) || (XPath.OP_NUMBER == predicateType)
+ || (XPath.FUNC_NUMBER == predicateType))
+ {
+ return false;
+ }
+ opPos = xpath.getNextOpPos(opPos);
+ nextStepType = xpath.m_opMap[opPos];
+ // Multiple predicates?
+ if(xpath.OP_PREDICATE == nextStepType)
+ return false;
+ }
+ return true;
+ }
+ break;
+ }
+ return false;
+ }
+
/**
*
* --------------------------------------------------------------------------------
@@ -1770,6 +1832,7 @@
if(tokenIs('/'))
{
nextToken();
+ int locationPathOpPos = opPos;
insertOp(opPos, 2, m_xpath.OP_LOCATIONPATH);
RelativeLocationPath();
@@ -1778,6 +1841,10 @@
m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] += 1;
m_xpath.m_opMap[opPos + m_xpath.MAPINDEX_LENGTH] = m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] - opPos;
+ if(isLocationPathSimpleFollowing(m_xpath, locationPathOpPos))
+ {
+ m_xpath.m_opMap[locationPathOpPos] = XPath.OP_LOCATIONPATH_EX;
+ }
}
}
@@ -1799,6 +1866,7 @@
if(tokenIs('['))
{
+ int locationPathOpPos = opPos;
insertOp(opPos, 2, m_xpath.OP_LOCATIONPATH);
while(tokenIs('['))
@@ -1817,6 +1885,10 @@
m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] += 1;
m_xpath.m_opMap[opPos + m_xpath.MAPINDEX_LENGTH] = m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] - opPos;
+ if(isLocationPathSimpleFollowing(m_xpath, locationPathOpPos))
+ {
+ m_xpath.m_opMap[locationPathOpPos] = XPath.OP_LOCATIONPATH_EX;
+ }
}
/*
@@ -1974,6 +2046,7 @@
throws org.xml.sax.SAXException
{
int opPos = m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH];
+ int locationPathOpPos = opPos;
appendOp(2, m_xpath.OP_LOCATIONPATH);
if(tokenIs('/'))
@@ -1994,6 +2067,10 @@
m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] += 1;
m_xpath.m_opMap[opPos + m_xpath.MAPINDEX_LENGTH] = m_xpath.m_opMap[m_xpath.MAPINDEX_LENGTH] - opPos;
+ if(isLocationPathSimpleFollowing(m_xpath, locationPathOpPos))
+ {
+ m_xpath.m_opMap[locationPathOpPos] = XPath.OP_LOCATIONPATH_EX;
+ }
}
/**
@@ -2769,6 +2846,7 @@
}
break;
case XPath.OP_LOCATIONPATH:
+ case XPath.OP_LOCATIONPATH_EX:
System.out.println("OP_LOCATIONPATH"+" {");
int endPath = opPos+xpath.m_opMap[opPos+1]-1;
opPos+=2;
@@ -3204,6 +3282,7 @@
opPos++;
}
break;
+ case XPath.OP_LOCATIONPATH_EX:
case XPath.OP_LOCATIONPATH:
diagnoseOp2("OP_LOCATIONPATH", xpath, opPos);
int endPath = opPos+xpath.m_opMap[opPos+1]-1;
1.7 +56 -27 xml-xalan/src/org/apache/xalan/xpath/XPathSupport.java
Index: XPathSupport.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPathSupport.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- XPathSupport.java 1999/12/16 06:10:44 1.6
+++ XPathSupport.java 2000/02/13 16:42:41 1.7
@@ -72,9 +72,39 @@
/**
* Set the current context node list.
*/
- void setContextNodeList(NodeList nl);
+ public void pushContextNodeList(NodeList nl);
/**
+ * Pop the current context node list.
+ */
+ public void popContextNodeList();
+
+ /**
+ * Get the current context node list.
+ */
+ int getContextNodePosition();
+
+ /**
+ * Increment the current context node position.
+ */
+ void incrementContextNodePosition(Node node);
+
+ /**
+ * Decrement the current context node position.
+ */
+ void decrementContextNodePosition();
+
+ /**
+ * Get the current context node list.
+ */
+ void pushContextNodePosition();
+
+ /**
+ * Get the current context node list.
+ */
+ void popContextNodePosition();
+
+ /**
* Get the current context node.
*/
Node getCurrentNode();
@@ -85,6 +115,30 @@
void setCurrentNode(Node n);
/**
+ * Push the current XPath selection,
+ * needed for support of the last() function. Ugh.
+ */
+ void pushXPathContext(XPath xpath, XPathSupport execContext, Node contextNode,
+ PrefixResolver namespaceContext);
+
+ /**
+ * Pop the current XPathContext.
+ */
+ void popXPathContext();
+
+ /**
+ * Reexecute the last xpath context after the specified one.
+ */
+ XObject reExecuteXPathContext(XPath path, XPathSupport execContext, Node context)
+ throws SAXException;
+
+ /**
+ * Push a dummy XPathContext so we can tell that the top-level xpath isn't
+ * in effect.
+ */
+ public void pushDummyXPathContext();
+
+ /**
* Get the current namespace context for the xpath.
*/
PrefixResolver getNamespaceContext();
@@ -183,32 +237,7 @@
*/
public void addExtensionNamespace (String uri,
ExtensionFunctionHandler extNS);
-
- /**
- * Set a callback that may be called by XPath as nodes are located.
- * The callback will only be called if the XLocator determines that
- * the location path can process the nodes in document order.
- * If the callback is called, the nodes will not be put into the
- * node list, and the LocationPath will return an empty node list.
- * The callback will be set to null after the given LocationPath or
- * Union is processed.
- * @param callback Interface that implements the processLocatedNode method.
- * @param callbackInfo Object that will be passed to the processLocatedNode method.
- */
- public void setCallback(NodeCallback callback, Object callbackInfo);
-
- /**
- * Get the callback that may be called by XPath as nodes are located.
- * @return the current callback method.
- */
- public NodeCallback getCallback();
-
- /**
- * Get the object that will be passed to the processLocatedNode method.
- * @return object that will be passed to the processLocatedNode method.
- */
- public Object getCallbackInfo();
-
+
/**
* ThrowFoundIndex tells if FoundIndex should be thrown
* if index is found.
1.9 +204 -23 xml-xalan/src/org/apache/xalan/xpath/XPathSupportDefault.java
Index: XPathSupportDefault.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/XPathSupportDefault.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- XPathSupportDefault.java 2000/01/31 08:31:14 1.8
+++ XPathSupportDefault.java 2000/02/13 16:42:41 1.9
@@ -63,14 +63,216 @@
import java.net.URL;
import org.xml.sax.SAXException;
import org.xml.sax.DocumentHandler;
+import org.apache.xalan.xpath.xml.IntStack;
/**
- * Dummy class in order to make the XPath object happy
- * for diagnostic purposes.
+ * Default class for execution context when XPath is used by itself.
*/
public class XPathSupportDefault implements XPathSupport
{
/**
+ * Keep stack of positions within the current context list.
+ */
+ private IntStack m_contextCounts = new IntStack();
+
+ /**
+ * The current context node list.
+ */
+ private Stack m_contextNodeLists = new Stack();
+
+ /**
+ * The current xpath state. Note... it would be
+ * a good optimization to make our own class and
+ * pre-allocate the XPathContext objects.
+ */
+ private Stack m_xpathContextStates = new Stack();
+
+ /**
+ * Class to stort the state of the XPath for re-execution.
+ */
+ class XPathContext
+ {
+ XPath xpath;
+ XPathSupport execContext;
+ Node contextNode;
+ PrefixResolver namespaceContext;
+ int contextNodePosition;
+ NodeList contextNodeList;
+ XObject result = null;
+
+ XPathContext(XPath xpath, XPathSupport execContext, Node contextNode,
+ PrefixResolver namespaceContext)
+ {
+ this.xpath = xpath;
+ this.execContext = execContext;
+ this.namespaceContext = namespaceContext;
+ this.contextNode = contextNode;
+ if(m_contextCounts.empty())
+ {
+ contextNodePosition = -200;
+ contextNodeList = null;
+ }
+ else
+ {
+ contextNodePosition = getContextNodePosition();
+ contextNodeList = getContextNodeList();
+ }
+ }
+
+ XObject execute()
+ throws SAXException
+ {
+ if(null != result)
+ return result;
+
+ m_contextNodeLists.push(contextNodeList);
+ m_contextCounts.push(contextNodePosition);
+ try
+ {
+ result = xpath.execute(execContext, contextNode,
+ namespaceContext);
+ }
+ finally
+ {
+ m_contextNodeLists.pop();
+ m_contextCounts.pop();
+ }
+ return result;
+
+ }
+
+ }
+
+ private XPathContext m_dummyXPathContext = new XPathContext(null, null, null, null);
+
+ /**
+ * Push the current XPath selection,
+ * needed for support of the last() function. Ugh.
+ */
+ public void pushXPathContext(XPath xpath, XPathSupport execContext, Node contextNode,
+ PrefixResolver namespaceContext)
+ {
+ XPathContext xpathContext
+ = new XPathContext(xpath, execContext, contextNode,
+ namespaceContext);
+ m_xpathContextStates.push(xpathContext);
+ }
+
+ /**
+ * Pop the current XPathContext.
+ */
+ public void popXPathContext()
+ {
+ m_xpathContextStates.pop();
+ }
+
+ /**
+ * Push a dummy XPathContext so we can tell that the top-level xpath isn't
+ * in effect.
+ */
+ public void pushDummyXPathContext()
+ {
+ m_xpathContextStates.push(m_dummyXPathContext);
+ }
+
+
+ /**
+ * Reexecute the xpath context below the specified one.
+ */
+ public XObject reExecuteXPathContext(XPath path, XPathSupport execContext, Node context)
+ throws SAXException
+ {
+ int size = m_xpathContextStates.size();
+ for(int i = (size-1); i >= 0; i--)
+ {
+ XPathContext xpathContext = (XPathContext)m_xpathContextStates.elementAt(i);
+ if(null == xpathContext.xpath)
+ return null;
+
+ if((xpathContext.contextNode == context)
+ && (xpathContext.xpath == path)
+ && (xpathContext.execContext == context))
+ continue;
+
+ return xpathContext.execute();
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the current context node list.
+ */
+ public int getContextNodePosition()
+ {
+ if(!m_contextCounts.empty())
+ return m_contextCounts.peek();
+ else
+ return -200;
+ }
+
+ /**
+ * Increment the current context node position.
+ */
+ public void incrementContextNodePosition(Node node)
+ {
+ int newNodePos = getContextNodePosition()+1;
+ m_contextCounts.setTop(newNodePos);
+ }
+
+ /**
+ * Decrement the current context node position.
+ */
+ public void decrementContextNodePosition()
+ {
+ m_contextCounts.setTop(getContextNodePosition()-1);
+ }
+
+ /**
+ * Get the current context node list.
+ */
+ public void pushContextNodePosition()
+ {
+ m_contextNodeLists.push(null);
+ m_contextCounts.push(0);
+ }
+
+ /**
+ * Get the current context node list.
+ */
+ public void popContextNodePosition()
+ {
+ m_contextNodeLists.pop();
+ m_contextCounts.pop();
+ }
+
+ /**
+ * Get the current context node list.
+ */
+ public NodeList getContextNodeList()
+ {
+ return (NodeList)m_contextNodeLists.peek();
+ }
+
+ /**
+ * Set the current context node list.
+ */
+ public void pushContextNodeList(NodeList nl)
+ {
+ m_contextCounts.push(-200);
+ m_contextNodeLists.push(nl);
+ }
+
+ /**
+ * Pop the current context node list.
+ */
+ public void popContextNodeList()
+ {
+ m_contextCounts.pop();
+ m_contextNodeLists.pop();
+ }
+
+ /**
* Tells if FoundIndex should be thrown if index is found.
* This is an optimization for match patterns.
*/
@@ -97,11 +299,6 @@
{
m_throwFoundIndex = b;
}
-
- /**
- * The current context node.
- */
- private NodeList m_contextNodeList = null;
/**
* The current node.
@@ -114,22 +311,6 @@
* (Is this really needed?)
*/
private PrefixResolver m_currentPrefixResolver = null;
-
- /**
- * Get the current context node list.
- */
- public NodeList getContextNodeList()
- {
- return m_contextNodeList;
- }
-
- /**
- * Set the current context node list.
- */
- public void setContextNodeList(NodeList nl)
- {
- m_contextNodeList = nl;
- }
/**
* Get the current context node.
1.1 xml-xalan/src/org/apache/xalan/xpath/EmptyNodeListImpl.java
Index: EmptyNodeListImpl.java
===================================================================
package org.apache.xalan.xpath;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Class to protect a MutableNodeListImpl from being written to. Really a
* debugging class.
*/
class EmptyNodeListImpl extends MutableNodeListImpl
{
EmptyNodeListImpl()
{
}
public void addNode(Node n)
{
// checkDups(n);
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Insert a node at a given position.
*/
public void insertNode(Node n, int pos)
{
// checkDups(n);
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Remove a node.
*/
public void removeNode(Node n)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Set a item to null, so the list doesn't
* have to keep being compressed.
*/
public void setItemNull(int pos)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Copy NodeList members into this nodelist, adding in
* document order. If a node is null, don't add it.
*/
public void addNodes(NodeList nodelist)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Copy NodeList members into this nodelist, adding in
* document order. If a node is null, don't add it.
*/
public void addNodesInDocOrder(NodeList nodelist, XPathSupport support)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
}
/**
* Add the node into a vector of nodes where it should occur in
* document order.
* @param v Vector of nodes, presumably containing Nodes
* @param obj Node object.
* @param test true if we should test for doc order
* @return insertIndex.
*/
public int addNodeInDocOrder(Node node, boolean test, XPathSupport support)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
} // end addNodeInDocOrder(Vector v, Object obj)
/**
* Add the node into a vector of nodes where it should occur in
* document order.
* @param v Vector of nodes, presumably containing Nodes
* @param obj Node object.
*/
public int addNodeInDocOrder(Node node, XPathSupport support)
{
throw new RuntimeException("Programmer's error: EmptyNodeListImpl can not be written to.");
} // end addNodeInDocOrder(Vector v, Object obj)
}
1.2 +10 -3 xml-xalan/src/org/apache/xalan/xpath/xml/IntStack.java
Index: IntStack.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/IntStack.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- IntStack.java 1999/12/13 07:40:11 1.1
+++ IntStack.java 2000/02/13 16:42:43 1.2
@@ -108,8 +108,17 @@
removeElementAt(len - 1);
return i;
+ }
/**
+ * Quickly pops a number of items from the stack.
+ *
+ * @exception EmptyStackException if this stack is empty.
+ */
+ public void quickPop(int n)
+ {
+ m_firstFree -= n;
}
+
/**
* Looks at the object at the top of this stack without removing it
* from the stack.
@@ -127,10 +136,8 @@
return elementAt(len - 1);
}
/**
- * Looks at the object at the top of this stack without removing it
- * from the stack.
+ * Sets an object at a the top of the statck
*
- * @return the object at the top of this stack.
* @exception EmptyStackException if this stack is empty.
* @since JDK1.0
*/
1.2 +2 -2 xml-xalan/src/org/apache/xalan/xpath/xml/IntVector.java
Index: IntVector.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/IntVector.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- IntVector.java 1999/12/13 07:40:11 1.1
+++ IntVector.java 2000/02/13 16:42:43 1.2
@@ -62,8 +62,8 @@
public class IntVector
{
private int m_blocksize;
- private int m_map[];
- private int m_firstFree = 0;
+ public int m_map[]; // expose to package for direct access.
+ protected int m_firstFree = 0;
private int m_mapSize;
/**
1.4 +1 -1 xml-xalan/src/org/apache/xalan/xpath/xml/NodeVector.java
Index: NodeVector.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/NodeVector.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- NodeVector.java 2000/01/31 08:08:51 1.3
+++ NodeVector.java 2000/02/13 16:42:43 1.4
@@ -64,7 +64,7 @@
public class NodeVector
{
private int m_blocksize;
- private Node m_map[];
+ protected Node m_map[];
private int m_firstFree = 0;
private int m_mapSize;
1.20 +22 -68 xml-xalan/src/org/apache/xalan/xpath/xml/XMLParserLiaisonDefault.java
Index: XMLParserLiaisonDefault.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xpath/xml/XMLParserLiaisonDefault.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- XMLParserLiaisonDefault.java 2000/01/31 08:23:35 1.19
+++ XMLParserLiaisonDefault.java 2000/02/13 16:42:43 1.20
@@ -127,7 +127,6 @@
m_sourceDocs = new Hashtable();
m_formatterListener = null;
m_dataProviders = new Vector(1);
- m_contextNodeList = null;
}
/**
@@ -182,6 +181,12 @@
* @see extensions.html.
*/
public Hashtable m_extensionFunctionNamespaces = new Hashtable();
+
+ /**
+ * The table of extension namespaces.
+ * @serial
+ */
+ public Hashtable m_extensionNamespaces = new Hashtable();
/**
* Table of input documents.
@@ -241,7 +246,7 @@
* The object will be set to null after the next LocationPath or
* Union is processed.
*/
- private Object m_callbackInfo = null;
+ private Object m_callbackInfo = null;
/**
* Set a callback that may be called by XPath as nodes are located.
@@ -556,6 +561,7 @@
stream.defaultReadObject();
m_NSInfos = new Hashtable();
m_extensionFunctionNamespaces = new Hashtable();
+ m_extensionNamespaces = new Hashtable();
m_sourceDocs = new Hashtable();
}
catch(ClassNotFoundException cnfe)
@@ -1697,72 +1703,7 @@
// SECTION: Execution context state tracking
//==========================================================
private final void ____Execution_Context____(){}
-
- /**
- * The current context node.
- */
- private NodeList m_contextNodeList = null;
-
- /**
- * The current node.
- */
- private Node m_currentNode = null;
-
- /**
- * The current prefixResolver for the execution context (not
- * the source tree context).
- * (Is this really needed?)
- */
- private PrefixResolver m_currentPrefixResolver = null;
-
- /**
- * Get the current context node list.
- */
- public NodeList getContextNodeList()
- {
- return m_contextNodeList;
- }
-
- /**
- * Set the current context node list.
- */
- public void setContextNodeList(NodeList nl)
- {
- m_contextNodeList = nl;
- }
-
- /**
- * Get the current context node.
- */
- public Node getCurrentNode()
- {
- return m_currentNode;
- }
-
- /**
- * Set the current context node.
- */
- public void setCurrentNode(Node n)
- {
- m_currentNode = n;
- }
-
- /**
- * Get the current namespace context for the xpath.
- */
- public PrefixResolver getNamespaceContext()
- {
- return m_currentPrefixResolver;
- }
-
- /**
- * Get the current namespace context for the xpath.
- */
- public void setNamespaceContext(PrefixResolver pr)
- {
- m_currentPrefixResolver = pr;
- }
-
+
public NodeList getNodeSetByKey(Node doc, String name,
String ref,
org.apache.xalan.xpath.xml.PrefixResolver nscontext)
@@ -1803,6 +1744,19 @@
public void addExtensionNamespace (String uri,
ExtensionFunctionHandler extNS) {
m_extensionFunctionNamespaces.put (uri, extNS);
+ }
+
+ /**
+ * Register an element extension namespace handler. This handler provides
+ * functions for testing whether a function is known within the
+ * namespace and also for invoking the functions.
+ *
+ * @param uri the URI for the extension.
+ * @param extNS the extension handler.
+ */
+ public void addExtensionElementNamespace (String uri,
+ ExtensionFunctionHandler extNS) {
+ m_extensionNamespaces.put (uri, extNS);
}
/**
1.3 +1 -1 xml-xalan/src/org/apache/xalan/xslt/AVTPartXPath.java
Index: AVTPartXPath.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/AVTPartXPath.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- AVTPartXPath.java 1999/11/28 04:25:13 1.2
+++ AVTPartXPath.java 2000/02/13 16:42:44 1.3
@@ -91,7 +91,7 @@
m_xpath = factory.create();
xpathProcessor.initMatchPattern(m_xpath, val, nsNode);
- m_xpath.shrink();
+ // m_xpath.shrink();
}
/**
1.3 +56 -0 xml-xalan/src/org/apache/xalan/xslt/Counter.java
Index: Counter.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/Counter.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- Counter.java 2000/01/31 20:52:30 1.2
+++ Counter.java 2000/02/13 16:42:44 1.3
@@ -1,3 +1,59 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "XSLT4J" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
package org.apache.xalan.xslt;
import org.w3c.dom.Node;
1.2 +56 -0 xml-xalan/src/org/apache/xalan/xslt/CountersTable.java
Index: CountersTable.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/CountersTable.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- CountersTable.java 2000/01/31 08:01:09 1.1
+++ CountersTable.java 2000/02/13 16:42:44 1.2
@@ -1,3 +1,59 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 1999 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ * if any, must include the following acknowledgment:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowledgment may appear in the software itself,
+ * if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "XSLT4J" and "Apache Software Foundation" must
+ * not be used to endorse or promote products derived from this
+ * software without prior written permission. For written
+ * permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ * nor may "Apache" appear in their name, without prior written
+ * permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation and was
+ * originally based on software copyright (c) 1999, Lotus
+ * Development Corporation., http://www.lotus.com. For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
package org.apache.xalan.xslt;
import java.util.Hashtable;
1.5 +17 -12 xml-xalan/src/org/apache/xalan/xslt/ElemCallTemplate.java
Index: ElemCallTemplate.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/ElemCallTemplate.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ElemCallTemplate.java 2000/01/05 23:05:30 1.4
+++ ElemCallTemplate.java 2000/02/13 16:42:44 1.5
@@ -114,18 +114,23 @@
}
if(null != m_template)
{
- processor.m_variableStacks.pushContextMarker(m_template, sourceNode);
-
- processor.m_variableStacks.pushParams(processor.getExecContext(),
- m_stylesheet,
- this,
- sourceTree,
- sourceNode, mode, m_template);
-
- // template.executeChildren(processor, sourceTree, sourceNode, mode);
- m_template.execute(processor, sourceTree, sourceNode, mode);
-
- processor.m_variableStacks.popCurrentContext();
+ try
+ {
+ processor.m_variableStacks.pushContextMarker(m_template, sourceNode);
+
+ processor.m_variableStacks.pushParams(processor.getExecContext(),
+ m_stylesheet,
+ this,
+ sourceTree,
+ sourceNode, mode, m_template);
+
+ // template.executeChildren(processor, sourceTree, sourceNode, mode);
+ m_template.execute(processor, sourceTree, sourceNode, mode);
+ }
+ finally
+ {
+ processor.m_variableStacks.popCurrentContext();
+ }
}
else
{
1.5 +30 -3 xml-xalan/src/org/apache/xalan/xslt/ElemExtensionCall.java
Index: ElemExtensionCall.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/ElemExtensionCall.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ElemExtensionCall.java 1999/12/14 00:21:54 1.4
+++ ElemExtensionCall.java 2000/02/13 16:42:44 1.5
@@ -63,19 +63,25 @@
import org.apache.xalan.xpath.xml.QName;
import org.apache.xalan.xpath.xml.NameSpace;
import org.apache.xalan.xpath.xml.StringToStringTable;
+import org.apache.xalan.xpath.xml.XMLParserLiaisonDefault;
import java.io.*;
import java.util.*;
public class ElemExtensionCall extends ElemLiteralResult
{
- ExtensionNSHandler nsh;
+ // ExtensionNSHandler nsh;
+ String m_extns;
+ String m_extHandlerLookup;
String localPart;
AttributeList m_attrs;
public Vector m_avts = null;
public StringToStringTable m_excludeResultPrefixes = null;
public String m_extensionElementPrefixes[] = null;
transient boolean isAvailable = false;
+ String m_lang;
+ String m_srcURL;
+ String m_scriptSrc;
public int getXSLToken()
{
@@ -84,7 +90,9 @@
ElemExtensionCall(XSLTEngineImpl processor,
Stylesheet stylesheetTree,
- ExtensionNSHandler nsh,
+ // ExtensionNSHandler nsh,
+ String extns,
+ String lang, String srcURL, String scriptSrc,
String name,
String localPart,
AttributeList atts,
@@ -93,7 +101,14 @@
{
super(processor, stylesheetTree, name, atts, lineNumber, columnNumber);
- this.nsh = nsh;
+ m_extHandlerLookup = new String("ElemExtensionCall:"+extns);
+ m_extns = extns;
+ m_lang = lang;
+ m_srcURL = srcURL;
+ m_scriptSrc = scriptSrc;
+
+ // this.nsh = nsh;
+ // processor.getXMLProcessorLiaison().addExtensionNamespace(m_extHandlerLookup, nsh);
this.localPart = localPart;
m_attrs = new AttributeListImpl(atts);
int nAttrs = atts.getLength();
@@ -171,6 +186,16 @@
try
{
processor.flushPending();
+ XMLParserLiaisonDefault liaison = ((XMLParserLiaisonDefault)processor.getXMLProcessorLiaison());
+ ExtensionNSHandler nsh
+ = (ExtensionNSHandler)liaison.m_extensionNamespaces.get(m_extns);
+
+ if(null == nsh)
+ {
+ nsh = new ExtensionNSHandler (processor, m_extns);
+ nsh.setScript (m_lang, m_srcURL, m_scriptSrc);
+ liaison.addExtensionElementNamespace(m_extns, nsh);
+ }
nsh.processElement (localPart, this,
processor,
m_stylesheet,
@@ -186,6 +211,8 @@
msg = msg.substring("Stopping after fatal error:".length());
}
processor.message("Call to extension element failed: "+msg);
+ // e.printStackTrace();
+ // System.exit(-1);
}
// processor.message(msg);
isAvailable = false;
1.16 +54 -53 xml-xalan/src/org/apache/xalan/xslt/ElemTemplateElement.java
Index: ElemTemplateElement.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/ElemTemplateElement.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- ElemTemplateElement.java 2000/02/11 23:07:50 1.15
+++ ElemTemplateElement.java 2000/02/13 16:42:44 1.16
@@ -748,18 +748,22 @@
if(null != selectPattern)
{
XPathSupport execContext = tcontext.getXMLProcessorLiaison();
- if(null != callback)
- execContext.setCallback(callback,
- new TemplateElementContext(stylesheetTree,
- xslInstruction,
- template,
- sourceNodeContext,
- mode,
- xslToken,
- tcontext));
+ // Optimization note: is there a way we can keep from creating
+ // a new callback context every time?
+ TemplateElementContext callbackContext
+ = (null != callback)
+ ? new TemplateElementContext(stylesheetTree,
+ xslInstruction,
+ template,
+ sourceNodeContext,
+ mode,
+ xslToken,
+ tcontext) : null;
+
XObject result = selectPattern.execute(execContext, sourceNodeContext,
- xslInstruction);
+ xslInstruction, callback,
+ callbackContext, false);
if(null != result)
{
sourceNodes = result.nodeset();
@@ -803,28 +807,33 @@
}
// NodeList children = sourceNodeContext.getChildNodes();
- NodeList savedContextNodeList = tcontext.getExecContext().getContextNodeList();
- tcontext.getExecContext().setContextNodeList( sourceNodes );
- if(tcontext.m_traceSelects)
- tcontext.traceSelect(xslInstruction, sourceNodes);
-
- for(int i = 0; i < nNodes; i++)
+ tcontext.getExecContext().pushContextNodeList( sourceNodes );
+ try
{
- Node childNode = sourceNodes.item(i);
+ if(tcontext.m_traceSelects)
+ tcontext.traceSelect(xslInstruction, sourceNodes);
- Document ownerDoc = childNode.getOwnerDocument();
- if((Node.DOCUMENT_NODE != childNode.getNodeType()) && (null == ownerDoc))
+ for(int i = 0; i < nNodes; i++)
{
- error(XSLTErrorResources.ER_NO_OWNERDOC, null); //"Child node does not have an owner document!");
+ Node childNode = sourceNodes.item(i);
+
+ Document ownerDoc = childNode.getOwnerDocument();
+ if((Node.DOCUMENT_NODE != childNode.getNodeType()) && (null == ownerDoc))
+ {
+ error(XSLTErrorResources.ER_NO_OWNERDOC, null); //"Child node does not have an owner document!");
+ }
+
+ transformChild(
+ stylesheetTree, xslInstruction, template,
+ ownerDoc,
+ sourceNodeContext, childNode,
+ mode, xslToken, tcontext);
}
-
- transformChild(
- stylesheetTree, xslInstruction, template,
- ownerDoc,
- sourceNodeContext, childNode,
- mode, xslToken, tcontext);
+ }
+ finally
+ {
+ tcontext.getExecContext().popContextNodeList();
}
- tcontext.getExecContext().setContextNodeList( savedContextNodeList );
}
}
else if(null == selectPattern)
@@ -836,31 +845,10 @@
{
error(XSLTErrorResources.ER_NO_OWNERDOC, null); //"Child node does not have an owner document!");
}
- NodeList savedContextNodeList = tcontext.getExecContext().getContextNodeList();
- MutableNodeList contextNodeList = new MutableNodeListImpl();
- tcontext.getExecContext().setContextNodeList( contextNodeList );
- /*
- // This isn't much faster than the block below...
try
{
- org.apache.xalan.xpath.dtm.DTMProxy contextp = (org.apache.xalan.xpath.dtm.DTMProxy)sourceNodeContext;
- org.apache.xalan.xpath.dtm.DTM dtm = contextp.getDTM();
- int contextIndex = contextp.getDTMNodeNumber();
- for(int child = dtm.getFirstChild(contextIndex);
- child != -1; child = dtm.getNextSibling(child))
- {
- Node childNode = dtm.getNode(child);
- contextNodeList.addNode(childNode);
- transformChild(
- stylesheetTree, xslInstruction, template,
- ownerDoc,
- sourceNodeContext, childNode,
- mode, xslToken, tcontext);
- }
- }
- catch(ClassCastException cce)
- */
- {
+ MutableNodeList contextNodeList = new MutableNodeListImpl();
+ tcontext.getExecContext().pushContextNodeList( contextNodeList );
for(Node childNode = sourceNodeContext.getFirstChild();
null != childNode; childNode = childNode.getNextSibling())
{
@@ -877,7 +865,10 @@
mode, xslToken, tcontext);
}
}
- tcontext.getExecContext().setContextNodeList( savedContextNodeList );
+ finally
+ {
+ tcontext.getExecContext().popContextNodeList();
+ }
}
}
@@ -944,15 +935,25 @@
templateContext.m_xslToken,
templateContext.m_transformContext
);
+ }
+ catch(java.net.MalformedURLException mue)
+ {
+ throw new XSLProcessorException(mue);
+ }
+ catch(java.io.FileNotFoundException fnfe)
+ {
+ throw new XSLProcessorException(fnfe);
}
- catch(SAXException se)
+ catch(java.io.IOException ioe)
{
- throw se;
+ throw new XSLProcessorException(ioe);
}
+ /*
catch(Exception mue)
{
throw new XSLProcessorException(mue);
}
+ */
}
/**
1.4 +2 -1 xml-xalan/src/org/apache/xalan/xslt/ElemValueOf.java
Index: ElemValueOf.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/ElemValueOf.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- ElemValueOf.java 2000/01/05 23:05:32 1.3
+++ ElemValueOf.java 2000/02/13 16:42:44 1.4
@@ -179,7 +179,8 @@
}
else
{
- XObject value = m_selectPattern.execute(processor.getExecContext(), sourceNode, this);
+ XObject value = m_selectPattern.execute(processor.getExecContext(), sourceNode, this,
+ null, null, true);
if(null != m_stylesheet.m_stylesheetRoot.m_traceListeners)
{
1.26 +2 -2 xml-xalan/src/org/apache/xalan/xslt/Stylesheet.java
Index: Stylesheet.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/Stylesheet.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- Stylesheet.java 2000/02/09 20:11:11 1.25
+++ Stylesheet.java 2000/02/13 16:42:44 1.26
@@ -1340,7 +1340,7 @@
XPath xpath = m_xpathFactory.create();
m_xpathProcessor.initXPath(xpath, str, nsNode);
- xpath.shrink();
+ // xpath.shrink();
return xpath;
}
@@ -1365,7 +1365,7 @@
XPath xpath = m_xpathFactory.create();
m_xpathProcessor.initMatchPattern(xpath, str, nsNode);
- xpath.shrink();
+ // xpath.shrink();
return xpath;
}
1.16 +13 -1 xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java
Index: StylesheetHandler.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/StylesheetHandler.java,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- StylesheetHandler.java 2000/02/10 20:06:31 1.15
+++ StylesheetHandler.java 2000/02/13 16:42:44 1.16
@@ -220,6 +220,7 @@
Locator locator = (Locator)m_processor.m_stylesheetLocatorStack.pop();
// System.out.println("popping locator for: "+locator.getPublicId());
}
+ m_stylesheet.m_extensionNamespaces.clear();
}
/**
@@ -1025,6 +1026,7 @@
// BEGIN SANJIVA CODE
// is this an extension element call?
ExtensionNSHandler nsh = null;
+ String theExtns = null;
if(null != ns)
{
@@ -1058,6 +1060,7 @@
if((ns != null) && ns.equals(extns))
{
nsh = new ExtensionNSHandler (m_processor, extns);
+ theExtns = extns;
break;
}
}
@@ -1095,6 +1098,7 @@
if((ns != null) && ns.equals(extns))
{
nsh = new ExtensionNSHandler (m_processor, extns);
+ theExtns = extns;
break;
}
}
@@ -1107,13 +1111,21 @@
if ((ns != null) && (null == nsh))
{
nsh = m_stylesheet.lookupExtensionNSHandler(ns);
+ theExtns = ns;
}
if (nsh != null)
{
+ if(null == theExtns)
+ theExtns = "";
+
elem = new ElemExtensionCall (m_processor,
m_stylesheet,
- nsh,
+ // nsh,
+ theExtns,
+ nsh.scriptLang,
+ nsh.scriptSrcURL,
+ nsh.scriptSrc,
name,
localName,
atts, lineNumber, columnNumber);
1.36 +10 -0 xml-xalan/src/org/apache/xalan/xslt/XSLTEngineImpl.java
Index: XSLTEngineImpl.java
===================================================================
RCS file: /home/cvs/xml-xalan/src/org/apache/xalan/xslt/XSLTEngineImpl.java,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -r1.35 -r1.36
--- XSLTEngineImpl.java 2000/02/11 15:42:39 1.35
+++ XSLTEngineImpl.java 2000/02/13 16:42:44 1.36
@@ -3313,6 +3313,16 @@
{
m_flistener = flistener;
}
+
+ /**
+ * Set a DOM document factory, primarily for creating result
+ * tree fragments.
+ */
+ public void setDOMFactory(Document doc)
+ {
+ m_resultTreeFactory = doc;
+ }
+
/**
* Get a DOM document, primarily for creating result