sboag 99/12/12 23:52:10
Modified: src/org/apache/xalan/xpath SimpleNodeLocator.java
XLocator.java
Log:
Added union method to XLocator interface. Tried depth-first union searches,
but put it on hold for the time being... code is commented out for right now.
Revision Changes Path
1.4 +601 -180
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.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SimpleNodeLocator.java 1999/11/28 10:26:16 1.3
+++ SimpleNodeLocator.java 1999/12/13 07:52:10 1.4
@@ -204,8 +204,120 @@
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;
+ }
+ */
+
+
+ /**
+ * 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.
+ * @returns the union of node-set operands, or an empty set if
+ * callback methods are used.
+ */
+ public XNodeSet union(XPath xpath, XPathSupport execContext,
+ Node context, int opPos)
+ 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.
+
+ UnionContext unionContext = new UnionContext(xpath.m_opMap, opPos);
+
+ MutableNodeList mnl = depthStep(xpath, execContext, context,
unionContext, 1);
+ }
+ else
+ */
+ {
+ opPos = xpath.getFirstChildPos(opPos);
+
+ while(xpath.m_opMap[opPos] == xpath.OP_LOCATIONPATH)
+ {
+ int nextOpPos = xpath.getNextOpPos(opPos);
+
+ XNodeSet expr = (XNodeSet)xpath.execute(execContext, context, opPos);
+ if(null == resultNodeSet)
+ {
+ resultNodeSet = expr;
+ }
+ else
+ {
+ MutableNodeList nl = resultNodeSet.mutableNodeset();
+ nl.addNodesInDocOrder(expr.nodeset(), execContext);
+ }
+ opPos = nextOpPos;
+ }
+ }
+
+ return resultNodeSet;
+ }
+
+ /**
* Execute a location path. Normally, this method simply
* moves past the OP_LOCATIONPATH and it's length member,
* and calls the Step function, which will recursivly process
@@ -216,10 +328,11 @@
* @param opPos The current position in the xpath.m_opMap array.
* @returns the result of the query in an XNodeSet object.
*/
- public XNodeSet locationPath(XPath xpath, XPathSupport execContext, Node
context, int opPos)
+ public XNodeSet locationPath(XPath xpath, XPathSupport execContext,
+ Node context, int opPos)
throws org.xml.sax.SAXException
{
- opPos+=2;
+ opPos = xpath.getFirstChildPos(opPos);
XNodeSet results;
MutableNodeList mnl = step(xpath, execContext, context, opPos);
if(null != mnl)
@@ -235,6 +348,310 @@
}
/**
+ * 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;
+ }
+
+ /**
+ * 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,
@@ -395,94 +812,6 @@
}
/**
- * Execute a step that performs an OP_VARIABLE, OP_EXTFUNCTION,
- * OP_FUNCTION, or OP_GROUP function.
- * @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 One of OP_VARIABLE, OP_EXTFUNCTION,
- * OP_FUNCTION, or OP_GROUP.
- * @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 findNodeSet(XPath xpath, XPathSupport execContext, Node
context, int opPos,
- int stepType, MutableNodeList subQueryResults)
- 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];
- }
-
- /**
- * Execute a step to the root.
- * @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 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)
- throws org.xml.sax.SAXException
- {
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
-
- Document docContext = (Node.DOCUMENT_NODE == context.getNodeType())
- ? (Document)context : context.getOwnerDocument();
- subQueryResults.addNode(docContext);
- return argLen+3;
- }
-
- /**
- * Add the parent 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_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)
- throws org.xml.sax.SAXException
- {
- context = execContext.getParentOfNode(context);
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- if(null != context)
- {
- opPos += 3;
- if(argLen > 0)
- {
- if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
- {
- subQueryResults.addNode(context);
- }
- }
- else
- {
- subQueryResults.addNode(context);
- }
- }
- return argLen+3;
- }
-
- /**
* 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.
@@ -497,8 +826,8 @@
int stepType, MutableNodeList subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
if(argLen > 0)
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
@@ -512,65 +841,7 @@
}
return argLen+3;
}
-
- /**
- * Add ancestors 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.
- * @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)
- throws org.xml.sax.SAXException
- {
- context = execContext.getParentOfNode(context);
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
- while(null != context)
- {
- if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
- {
- subQueryResults.addNode(context);
- }
- context = execContext.getParentOfNode(context);
- }
- return argLen+3;
- }
-
- /**
- * 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 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)
- throws org.xml.sax.SAXException
- {
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
- while(null != context)
- {
- if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
- {
- subQueryResults.addNode(context);
- }
- context = execContext.getParentOfNode(context);
- }
- return argLen+3;
- }
-
+
/**
* Add attributes to the list if they meet
* the NodeTest qualification.
@@ -587,8 +858,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
if( (null != context) && (context.getNodeType()==Node.ELEMENT_NODE) )
{
NamedNodeMap attributeList = context.getAttributes();
@@ -624,8 +895,8 @@
int stepType, MutableNodeList subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
// If using a document fragment with references (non-standard)
// we can not use the next-sibling business at the top level.
if(Node.DOCUMENT_FRAGMENT_NODE != context.getNodeType())
@@ -635,6 +906,8 @@
{
if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, c, opPos,
argLen, stepType))
{
+ // or else call execute method. If no execute method,
+ // add the node.
subQueryResults.addNode(c);
}
c = c.getNextSibling();
@@ -674,8 +947,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
// Perform a pre-order traversal of descendents.
// Note that I would like to be able to do optimization here
@@ -787,8 +1060,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
// What fun...
Document doc = context.getOwnerDocument();
@@ -844,8 +1117,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
Node pos = context.getNextSibling();
while(null != pos)
@@ -859,6 +1132,153 @@
return argLen+3;
}
+
+ /**
+ * Execute a step that performs an OP_VARIABLE, OP_EXTFUNCTION,
+ * OP_FUNCTION, or OP_GROUP function.
+ * @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 One of OP_VARIABLE, OP_EXTFUNCTION,
+ * OP_FUNCTION, or OP_GROUP.
+ * @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 findNodeSet(XPath xpath, XPathSupport execContext, Node
context, int opPos,
+ int stepType, MutableNodeList subQueryResults)
+ 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];
+ }
+
+ /**
+ * Execute a step to the root.
+ * @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 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)
+ throws org.xml.sax.SAXException
+ {
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
+
+ Document docContext = (Node.DOCUMENT_NODE == context.getNodeType())
+ ? (Document)context : context.getOwnerDocument();
+ subQueryResults.addNode(docContext);
+ return argLen+3;
+ }
+
+ /**
+ * Add the parent 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_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)
+ throws org.xml.sax.SAXException
+ {
+ context = execContext.getParentOfNode(context);
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ if(null != context)
+ {
+ opPos = xpath.getFirstChildPosOfStep(opPos);
+ if(argLen > 0)
+ {
+ if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
+ {
+ subQueryResults.addNode(context);
+ }
+ }
+ else
+ {
+ subQueryResults.addNode(context);
+ }
+ }
+ return argLen+3;
+ }
+
+ /**
+ * Add ancestors 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.
+ * @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)
+ throws org.xml.sax.SAXException
+ {
+ context = execContext.getParentOfNode(context);
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
+ while(null != context)
+ {
+ if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
+ {
+ subQueryResults.addNode(context);
+ }
+ context = execContext.getParentOfNode(context);
+ }
+ return argLen+3;
+ }
+
+ /**
+ * 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 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)
+ throws org.xml.sax.SAXException
+ {
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
+ while(null != context)
+ {
+ if(xpath.MATCH_SCORE_NONE != nodeTest(xpath, execContext, context,
opPos, argLen, stepType))
+ {
+ subQueryResults.addNode(context);
+ }
+ context = execContext.getParentOfNode(context);
+ }
+ return argLen+3;
+ }
+
/**
* Add the nodes preceding the context to the list if they meet
* the NodeTest qualification.
@@ -883,8 +1303,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
// Ugh. Reverse document order, no parents, I guess.
Document doc = context.getOwnerDocument();
@@ -952,8 +1372,8 @@
int stepType, MutableNodeList
subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
Node pos = context.getPreviousSibling();
while(null != pos)
@@ -982,8 +1402,8 @@
int stepType, MutableNodeList subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
xpath.error(context, XPATHErrorResources.ERROR0014); //"namespace axis
not implemented yet!");
return argLen+3;
}
@@ -1003,8 +1423,8 @@
int stepType, MutableNodeList subQueryResults)
throws org.xml.sax.SAXException
{
- int argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ int argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
xpath.error(context, XPATHErrorResources.ERROR0015, new Object[]
{Integer.toString(stepType)}); //"unknown axis: "+stepType);
return argLen+3;
}
@@ -1080,7 +1500,7 @@
public double locationPathPattern(XPath xpath, XPathSupport execContext,
Node context, int opPos)
throws org.xml.sax.SAXException
{
- opPos+=2;
+ opPos = xpath.getFirstChildPos(opPos);
double[] scoreHolder = {xpath.MATCH_SCORE_NONE};
stepPattern(xpath, execContext, context, opPos, scoreHolder);
return scoreHolder[0];
@@ -1142,8 +1562,8 @@
break;
case xpath.FROM_ROOT:
{
- argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
Document docContext = (Node.DOCUMENT_NODE == context.getNodeType())
? (Document)context :
context.getOwnerDocument();
score = (docContext == context) ? xpath.MATCH_SCORE_OTHER :
xpath.MATCH_SCORE_NONE;
@@ -1155,15 +1575,15 @@
break;
case xpath.MATCH_ATTRIBUTE:
{
- argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
score = nodeTest(xpath, execContext, context, opPos, argLen,
xpath.FROM_ATTRIBUTES);
break;
}
case xpath.MATCH_ANY_ANCESTOR:
{
- argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
score = xpath.MATCH_SCORE_NONE;
while(null != context)
{
@@ -1175,13 +1595,13 @@
}
break;
case xpath.MATCH_IMMEDIATE_ANCESTOR:
- argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
score = nodeTest(xpath, execContext, context, opPos, argLen, stepType);
break;
default:
- argLen = xpath.m_opMap[opPos+xpath.MAPINDEX_LENGTH+1]-3;
- opPos += 3;
+ argLen = xpath.getArgLengthOfStep(opPos);
+ opPos = xpath.getFirstChildPosOfStep(opPos);
score = xpath.MATCH_SCORE_NONE;
xpath.error(context, XPATHErrorResources.ERROR0016); //"unknown match
operation!");
break;
@@ -1197,6 +1617,7 @@
// if I could sense this condition earlier...
try
{
+ // BUG: m_throwFoundIndex is not threadsafe
xpath.m_throwFoundIndex = true;
int startPredicates = opPos;
opPos = startPredicates;
1.4 +11 -0 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.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- XLocator.java 1999/11/28 10:26:16 1.3
+++ XLocator.java 1999/12/13 07:52:10 1.4
@@ -89,6 +89,17 @@
throws org.xml.sax.SAXException;
/**
+ * Execute a union. The union of its operands, which are locationPaths,
+ * must be node-sets.
+ * @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 the result of the query in an XNodeSet object.
+ */
+ XNodeSet union(XPath xpath, XPathSupport execContext, Node context, int
opPos)
+ throws org.xml.sax.SAXException;
+
+ /**
* Execute a location path. Normally, this method simply
* moves past the OP_LOCATIONPATH and it's length member,
* and calls the Step function, which will recursivly process