Hi Mark,

Yes, there were some spots in the code where node-sets were ordered, but we
were assuming they were unordered.  That lead to duplicate effort, and
since we always have to apply node-sets in document order, it makes sense
to order them appropriately when producing them and enforce that
requirement.

This may just be some broken assumptions we're making in the Xalan code
about what's in a node-set, and whether or not it can always be ordered.
Another thing to remember about result tree fragments is they each must
have a separate owner document if they are going to be turned into a
node-set.

Can you put together a small sample that I can build to reproduce the
problem and attach that to a new bug report?  That would help me to figure
out exactly what's going on and how it can be fixed.

Thanks!

Dave



|---------+--------------------------->
|         |           "Mark Weaver"   |
|         |           <[EMAIL PROTECTED]|
|         |           >               |
|         |                           |
|         |           03/22/2003 07:10|
|         |           AM              |
|---------+--------------------------->
  
>--------------------------------------------------------------------------------------------------------------------------------|
  |                                                                             
                                                   |
  |        To:      "Xalan-C-Users" <[email protected]>              
                                                   |
  |        cc:      (bcc: David N Bertoni/Cambridge/IBM)                        
                                                   |
  |        Subject: my naughty dictionary function                              
                                                   |
  
>--------------------------------------------------------------------------------------------------------------------------------|



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