You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by il...@apache.org on 2002/11/25 23:15:07 UTC
cvs commit: xml-xalan/java/src/org/apache/xpath/objects NodeSequence.java
ilene 2002/11/25 14:15:07
Modified: java/src/org/apache/xalan/templates Tag: xslt20 FuncKey.java
java/src/org/apache/xalan/transformer Tag: xslt20
TransformerImpl.java KeyTable.java
java/src/org/apache/xpath/objects Tag: xslt20
NodeSequence.java
Removed: java/src/org/apache/xalan/transformer Tag: xslt20
KeyRefIterator.java
Log:
Propogating patches from main branch to XSLT20 branch.
Bugs patched are #11661, 11834, 10176.
The fix for 10176 fixes testcase position102 on the XSLT20 branch.
Revision Changes Path
No revision
No revision
1.14.4.1.2.2 +1 -1 xml-xalan/java/src/org/apache/xalan/templates/FuncKey.java
Index: FuncKey.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/templates/FuncKey.java,v
retrieving revision 1.14.4.1.2.1
retrieving revision 1.14.4.1.2.2
diff -u -r1.14.4.1.2.1 -r1.14.4.1.2.2
--- FuncKey.java 11 Nov 2002 19:51:16 -0000 1.14.4.1.2.1
+++ FuncKey.java 25 Nov 2002 22:15:07 -0000 1.14.4.1.2.2
@@ -109,7 +109,7 @@
XNodeSet nodes = null;
int context = xctxt.getCurrentNode();
DTM dtm = xctxt.getDTM(context);
- int docContext = dtm.getDocument();
+ int docContext = dtm.getDocumentRoot(context);
if (DTM.NULL == docContext)
{
No revision
No revision
1.133.2.1.2.2 +10 -5 xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java
Index: TransformerImpl.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/TransformerImpl.java,v
retrieving revision 1.133.2.1.2.1
retrieving revision 1.133.2.1.2.2
diff -u -r1.133.2.1.2.1 -r1.133.2.1.2.2
--- TransformerImpl.java 11 Oct 2002 21:23:19 -0000 1.133.2.1.2.1
+++ TransformerImpl.java 25 Nov 2002 22:15:07 -0000 1.133.2.1.2.2
@@ -2027,11 +2027,12 @@
DTM dtm = m_xcontext.getDTM(child);
short nodeType = dtm.getNodeType(child);
boolean isDefaultTextRule = false;
+ boolean isApplyImports = false;
if (null == template)
{
int maxImportLevel, endImportLevel=0;
- boolean isApplyImports = ((xslInstruction == null)
+ isApplyImports = ((xslInstruction == null)
? false
: xslInstruction.getXSLToken()
== Constants.ELEMNAME_APPLY_IMPORTS);
@@ -2121,8 +2122,10 @@
pushPairCurrentMatched(template, child);
// Fix copy copy29 test.
- DTMIterator cnl = new org.apache.xpath.NodeSetDTM(child, m_xcontext.getDTMManager());
- m_xcontext.pushContextNodeList(cnl);
+ if (!isApplyImports) {
+ DTMIterator cnl = new org.apache.xpath.NodeSetDTM(child, m_xcontext.getDTMManager());
+ m_xcontext.pushContextNodeList(cnl);
+ }
if (isDefaultTextRule)
{
@@ -2171,8 +2174,10 @@
{
m_xcontext.getVarStack().unlink();
m_xcontext.popCurrentNode();
- m_xcontext.popContextNodeList();
- popCurrentMatched();
+ if (!isApplyImports) {
+ m_xcontext.popContextNodeList();
+ popCurrentMatched();
+ }
popElemTemplateElement();
}
1.11.6.1 +156 -22 xml-xalan/java/src/org/apache/xalan/transformer/KeyTable.java
Index: KeyTable.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xalan/transformer/KeyTable.java,v
retrieving revision 1.11
retrieving revision 1.11.6.1
diff -u -r1.11 -r1.11.6.1
--- KeyTable.java 22 Mar 2002 01:04:41 -0000 1.11
+++ KeyTable.java 25 Nov 2002 22:15:07 -0000 1.11.6.1
@@ -60,23 +60,28 @@
import java.util.Vector;
import javax.xml.transform.TransformerException;
-import org.apache.xml.dtm.DTM;
+
+import org.apache.xml.utils.NodeVector;
import org.apache.xml.utils.PrefixResolver;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.XMLString;
+import org.apache.xml.utils.WrappedRuntimeException;
+import org.apache.xml.dtm.DTM;
+import org.apache.xml.dtm.DTMIterator;
import org.apache.xpath.XPathContext;
import org.apache.xpath.objects.XNodeSet;
+import org.apache.xpath.objects.XObject;
+import org.apache.xpath.objects.XNull;
+import org.apache.xalan.templates.KeyDeclaration;
/**
* <meta name="usage" content="advanced"/>
* Table of element keys, keyed by document node. An instance of this
* class is keyed by a Document node that should be matched with the
- * root of the current context. It contains a table of name mappings
- * to tables that contain mappings of identifier values to nodes.
+ * root of the current context.
*/
public class KeyTable
{
-
/**
* The document key. This table should only be used with contexts
* whose Document roots match this key.
@@ -84,9 +89,20 @@
private int m_docKey;
/**
+ * Vector of KeyDeclaration instances holding the key declarations.
+ */
+ private Vector m_keyDeclarations;
+
+ /**
+ * Hold a cache of key() function result for each ref.
+ * Key is XMLString, the ref value
+ * Value is XNodeSet, the key() function result for the given ref value.
+ */
+ private Hashtable m_refsTable = null;
+
+ /**
* Get the document root matching this key.
*
- *
* @return the document root matching this key
*/
public int getDocKey()
@@ -119,45 +135,163 @@
int doc, PrefixResolver nscontext, QName name, Vector keyDeclarations, XPathContext xctxt)
throws javax.xml.transform.TransformerException
{
-
m_docKey = doc;
+ m_keyDeclarations = keyDeclarations;
KeyIterator ki = new KeyIterator(name, keyDeclarations);
-
+
m_keyNodes = new XNodeSet(ki);
m_keyNodes.allowDetachToRelease(false);
-
- m_keyNodes.setRoot(xctxt.getDTM(doc).getDocument(), xctxt);
- }
+ m_keyNodes.setRoot(doc, xctxt);
+ }
/**
* Given a valid element key, return the corresponding node list.
*
- * @param The name of the key, which must match the 'name' attribute on xsl:key.
+ * @param name The name of the key, which must match the 'name' attribute on xsl:key.
* @param ref The value that must match the value found by the 'match' attribute on xsl:key.
- * @return If the name was not declared with xsl:key, this will return null,
- * if the identifier is not found, it will return null,
- * otherwise it will return a LocPathIterator instance.
+ * @return a set of nodes referenced by the key named <CODE>name</CODE> and the reference <CODE>ref</CODE>. If no node is referenced by this key, an empty node set is returned.
*/
public XNodeSet getNodeSetDTMByKey(QName name, XMLString ref)
+
{
- Vector keyDecls = getKeyIterator().getKeyDeclarations();
- org.apache.xml.dtm.DTMIterator keyNodes = m_keyNodes.iter();
- XNodeSet refNodes = new XNodeSet( new KeyRefIterator(name, ref, keyDecls, keyNodes) );
-
- // I don't think setRoot needs to be called on refNodes!
- return refNodes;
+ XNodeSet refNodes = (XNodeSet) getRefsTable().get(ref);
+ // clone wiht reset the node set
+ try
+ {
+ if (refNodes != null)
+ {
+ refNodes = (XNodeSet) refNodes.cloneWithReset();
+ }
+ }
+ catch (CloneNotSupportedException e)
+ {
+ refNodes = null;
+ }
+
+ if (refNodes == null) {
+ // create an empty XNodeSet
+ KeyIterator ki = (KeyIterator) (m_keyNodes).getContainedIter();
+ XPathContext xctxt = ki.getXPathContext();
+ refNodes = new XNodeSet(xctxt.getDTMManager()) {
+ public void setRoot(int nodeHandle, Object environment) {
+ // Root cannot be set on non-iterated node sets. Ignore it.
+ }
+ };
+ refNodes.reset();
+ }
+ return refNodes;
}
/**
* Get Key Name for this KeyTable
*
- *
* @return Key name
*/
public QName getKeyTableName()
{
return getKeyIterator().getName();
}
-
+
+ /**
+ * @return key declaration for the key associated to this KeyTable
+ */
+ private KeyDeclaration getKeyDeclaration() {
+ int nDeclarations = m_keyDeclarations.size();
+
+ // Walk through each of the declarations made with xsl:key
+ for (int i = 0; i < nDeclarations; i++)
+ {
+ KeyDeclaration kd = (KeyDeclaration) m_keyDeclarations.elementAt(i);
+
+ // Only continue if the name on this key declaration
+ // matches the name on the iterator for this walker.
+ if (kd.getName().equals(getKeyTableName()))
+ {
+ return kd;
+ }
+ }
+
+ // should never happen
+ return null;
+ }
+
+ /**
+ * @return lazy initialized refs table associating evaluation of key function
+ * with a XNodeSet
+ */
+ private Hashtable getRefsTable()
+ {
+ if (m_refsTable == null)
+ {
+ m_refsTable = new Hashtable(89); // initial capacity set to a prime number to improve hash algorithm performance
+
+ KeyIterator ki = (KeyIterator) (m_keyNodes).getContainedIter();
+ XPathContext xctxt = ki.getXPathContext();
+
+ KeyDeclaration keyDeclaration = getKeyDeclaration();
+
+ int currentNode;
+ m_keyNodes.reset();
+ while (DTM.NULL != (currentNode = m_keyNodes.nextNode()))
+ {
+ try
+ {
+ XObject xuse = keyDeclaration.getUse().execute(xctxt, currentNode, ki.getPrefixResolver());
+
+ if (xuse.getType() != xuse.CLASS_NODESET)
+ {
+ XMLString exprResult = xuse.xstr();
+ addValueInRefsTable(xctxt, exprResult, currentNode);
+ }
+ else
+ {
+ DTMIterator i = ((XNodeSet)xuse).iterRaw();
+ int currentNodeInUseClause;
+
+ while (DTM.NULL != (currentNodeInUseClause = i.nextNode()))
+ {
+ DTM dtm = xctxt.getDTM(currentNodeInUseClause);
+ XMLString exprResult = dtm.getStringValue(currentNodeInUseClause);
+ addValueInRefsTable(xctxt, exprResult, currentNode);
+ }
+ }
+ }
+ catch (TransformerException te)
+ {
+ throw new WrappedRuntimeException(te);
+ }
+ }
+ }
+ return m_refsTable;
+ }
+
+ /**
+ * Add an association between a ref and a node in the m_refsTable.
+ * Requires that m_refsTable != null
+ * @param xctxt XPath context
+ * @param ref the value of the use clause of the current key for the given node
+ * @param node the node to reference
+ */
+ private void addValueInRefsTable(XPathContext xctxt, XMLString ref, int node) {
+
+ XNodeSet nodes = (XNodeSet) m_refsTable.get(ref);
+ if (nodes == null)
+ {
+ nodes = new XNodeSet(node, xctxt.getDTMManager());
+ nodes.nextNode();
+ m_refsTable.put(ref, nodes);
+ }
+ else
+ {
+ // Nodes are passed to this method in document order. Since we need to
+ // suppress duplicates, we only need to check against the last entry
+ // in each nodeset. We use nodes.nextNode after each entry so we can
+ // easily compare node against the current node.
+ if (nodes.getCurrentNode() != node) {
+ nodes.mutableNodeset().addNode(node);
+ nodes.nextNode();
+ }
+ }
+ }
}
No revision
No revision
1.1.2.1.2.2 +9 -0 xml-xalan/java/src/org/apache/xpath/objects/Attic/NodeSequence.java
Index: NodeSequence.java
===================================================================
RCS file: /home/cvs/xml-xalan/java/src/org/apache/xpath/objects/Attic/NodeSequence.java,v
retrieving revision 1.1.2.1.2.1
retrieving revision 1.1.2.1.2.2
diff -u -r1.1.2.1.2.1 -r1.1.2.1.2.2
--- NodeSequence.java 11 Nov 2002 19:51:17 -0000 1.1.2.1.2.1
+++ NodeSequence.java 25 Nov 2002 22:15:07 -0000 1.1.2.1.2.2
@@ -66,6 +66,7 @@
import org.apache.xml.dtm.DTMFilter;
import org.apache.xml.utils.NodeVector;
import org.apache.xpath.Expression;
+import org.apache.xpath.NodeSetDTM;
import org.apache.xpath.VariableComposeState;
import org.apache.xpath.XPathContext;
import org.apache.xpath.axes.PathComponent;
@@ -565,6 +566,14 @@
{
if(hasCache())
{
+ // If this NodeSequence wraps a mutable nodeset, then
+ // m_last will not reflect the size of the nodeset if
+ // it has been mutated...
+ if (m_iter instanceof NodeSetDTM)
+ {
+ return m_iter.getLength();
+ }
+
if(-1 == m_last)
{
int pos = m_next;
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org