One of the changes I've noticed with 1.5 is that my naughty dictionary
function is broken.  This is a bad thing, because it's not XSLT like (i.e. not
strictly functional), but it's very handy.

Essentially it goes:

class FunctionDictionary : public Function
{
        virtual XObjectPtr
        execute(
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              /* context */,
                        const XObjectPtr            arg1,
                        const XObjectPtr            arg2,
                        const Locator*                  /* locator */) const
        {
                m_dic[arg1->str().data()] = arg2;
                return arg2;
        }

        virtual XObjectPtr
        execute(
                        XPathExecutionContext&  executionContext,
                        XalanNode*                              /* context */,
                        const Locator*                  /* locator */) const
        {
                XPathExecutionContext::BorrowReturnMutableNodeRefList
theNodeList(executionContext);
                for (dictionary_t::iterator it = m_dic.begin();
                        it != m_dic.end(); ++it) {

                        XalanNode* node = 
(*it).second->rtree().getNodesetRoot();
                        theNodeList->addNode(node);
                }
                // turn the document into a node set
                return 
executionContext.getXObjectFactory().createNodeSet(theNodeList);
        }

        typedef std::map<std::wstring, XObjectPtr> dictionary_t;
        mutable dictionary_t m_dic;
};

(There is also a corresponding single argument lookup method which isn't
interesting for this problem).

The XSLT does something like:

  <xsl:template name="foobar">
    <xsl:param name="id"/>
    <xsl:variable name="a">
      <node/>
    </xsl:variable>
    <xsl:variable name="q" select="gnomon:dictionary(concat('meep',$id),$a)"/>
  </xsl:template>

  <xsl:template match="/">
    <xsl:call-template name="foobar"><xsl:with-param 
name="id">1</xsl:with-param></xsl:call-template>
    <xsl:call-template name="foobar"><xsl:with-param 
name="id">2</xsl:with-param></xsl:call-template>
    <xsl:copy-of select="gnomon:dictionary()/meep1"/>
  </xsl:template>

Now it's OK with one invocation (just the call-template with id=1), but with 
two invocations there is an assertion failure in 
XalanSourceTreeDOMSupport::isNodeAfter:

        assert(node1.isIndexed() == true && node2.isIndexed() == true);

The nodes are result tree fragments, which correspond to 
XalanSourceTreeDocumentFragment, which return false in isIndexed().

Part of the problem here is that I have basically no idea what is going so some 
explanation would be handy :)  I believe the assumption is that the nodeset 
contains nodes selected from the document (which isn't unreasonable, I'm 
admittedly doing something really strange), so adding them in order would 
appear to be a (new since 1.4) optimisation.  Is that correct?

If so, is there something that I can do to solve this?  (e.g. copy the nodes; 
or copy the nodes to a different document -- the code appears to check when 
attempting to order the nodes if they are from the same document, which makes 
sense).

Thanks,

Mark

Reply via email to