Fix for Bugzilla entries
6833
7023
7123
7410
Basic summary of logic error: It is possible for multiple RTF DTMs
to be pushed onto the stack between the start of a template and
return from it. I hadn't anticipated that, so my pop logic was
inadequate.
I'm still not 110% sure I understand the case where this situation
arises... I have a general intuition that it makes sense, but also a
suspicion that there might be a way to avoid creating one of these
DTMs. We should review that someday.
Meanwhile, this fixes a whole batch of related bugs.
git-svn-id: https://svn.apache.org/repos/asf/xalan/java/trunk@336321 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/org/apache/xpath/XPathContext.java b/src/org/apache/xpath/XPathContext.java
index ffe4fdb..d6070e3 100644
--- a/src/org/apache/xpath/XPathContext.java
+++ b/src/org/apache/xpath/XPathContext.java
@@ -110,6 +110,7 @@
import org.apache.xml.utils.SAXSourceLocator;
import org.apache.xml.utils.XMLString;
import org.apache.xml.utils.XMLStringFactory;
+import org.apache.xml.utils.IntStack;
import org.apache.xpath.axes.DescendantIterator;
@@ -124,6 +125,7 @@
*/
public class XPathContext extends DTMManager // implements ExpressionContext
{
+ IntStack m_last_pushed_rtfdtm=new IntStack();
/**
* Stack of cached "reusable" DTMs for Result Tree Fragments.
* This is a kluge to handle the problem of starting an RTF before
@@ -1270,6 +1272,10 @@
m_rtfdtm_stack.addElement(rtfdtm);
++m_which_rtfdtm;
}
+ else if(m_which_rtfdtm<0)
+ {
+ rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(++m_which_rtfdtm);
+ }
else
{
rtfdtm=(SAX2RTFDTM)m_rtfdtm_stack.elementAt(m_which_rtfdtm);
@@ -1277,8 +1283,9 @@
// It might already be under construction -- the classic example would be
// an xsl:variable which uses xsl:call-template as part of its value. To
// handle this recursion, we have to start a new RTF DTM, pushing the old
- // one onto a stack so we can return to it. It is hoped that
- // this is an uncommon case!
+ // one onto a stack so we can return to it. This is not as uncommon a case
+ // as we might wish, unfortunately, as some folks insist on coding XSLT
+ // as if it were a procedural language...
if(rtfdtm.isTreeIncomplete())
{
if(++m_which_rtfdtm < m_rtfdtm_stack.size())
@@ -1290,6 +1297,7 @@
}
}
}
+
return rtfdtm;
}
@@ -1299,6 +1307,7 @@
* */
public void pushRTFContext()
{
+ m_last_pushed_rtfdtm.push(m_which_rtfdtm);
if(null!=m_rtfdtm_stack)
((SAX2RTFDTM)(getRTFDTM())).pushRewindMark();
}
@@ -1321,11 +1330,22 @@
{
if(null==m_rtfdtm_stack)
return;
-
- boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark();
- if(isEmpty && m_which_rtfdtm>0)
- {
- --m_which_rtfdtm;
- }
+
+ int previous=m_last_pushed_rtfdtm.pop();
+ if(m_which_rtfdtm==previous)
+ {
+ if(previous>=0) // guard against none-active
+ {
+ boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(previous))).popRewindMark();
+ }
+ }
+ else while(m_which_rtfdtm!=previous)
+ {
+ // Empty each DTM before popping, so it's ready for reuse
+ // _DON'T_ pop the previous, since it's still open (which is why we
+ // stacked up more of these) and did not receive a mark.
+ boolean isEmpty=((SAX2RTFDTM)(m_rtfdtm_stack.elementAt(m_which_rtfdtm))).popRewindMark();
+ --m_which_rtfdtm;
+ }
}
}