David,

        Excellent! No more Abort on the use of the returned fragment from the 
external XPath function.

May I suggest that this concept get added as a samples example? I find it to 
be such an expected "Use Case" that I was surprised not to find it there 
already - and, as I wrote, I never would have guessed how to send back the 
new Document node.

Lonnie.

On Wednesday 25 May 2005 12:17 pm, Lonnie VanZandt wrote:
> Although not yet tested, the code sample provided was nearly compilable
> (and now is after a few tweaks):
>
>       size_type is defined in a variety of Xalan* classes, to get the proper
> one, when the implementation code of the class is placed in a cc file
> rather than in an hpp file, one has to namespace scope it to
> NodeRefListBase::size_type even if a XALAN_USING_XALAN(NodeRefListBase)
> declaration is provided. No big deal.
>
>       The NodeSetProxy constructor should take a Xalan MemoryManagerType 
> rather
> than a Xerces MemoryManager. This makes the constructors for the wrapper
> and the proxy happy.
>
>       The call to construct the XNodeSetNodeProxy also requires that the 
> manager
> reference be passed along.
>
> Now to test the result!
>
> On Wednesday 25 May 2005 09:45 am, Lonnie VanZandt wrote:
> > I agree with you that the runtime warning from the code about calling a
> > pure virtual function is indeed very odd because of how C++ should work
> > and because other code which uses the other XObjectFactory methods (such
> > as createNumber) do not trigger that warning yet are also pure virtuals
> > in the super class.
> >
> > I also realized last night that it doesn't suffice to copy the node
> > references into the mutable node reference list for the DOM document
> > because the target Document node (and its children) are not yet owned by
> > something of greater scope than the immediate stack frame. I was seeking
> > a createDocument method of either the executionContext or the
> > executionContext's XObjectFactory.
> >
> > Although I never would have guessed the solution you propose, having it
> > before me I can see how and why it might succeed.
> >
> > I do believe that in step 3 below, I will need to change the call to
> > "myProxy" to "myNodeSet"...
> >
> > Thank you for your prompt reply (and for an impressive collection of code
> > in Xalan-C++).
> >
> > On Tuesday 24 May 2005 11:41 pm, [EMAIL PROTECTED] wrote:
> > > > While attempting to see if this "just works", I find that the call to
> > > > executionContext.getXObjectFactory().createNodeSet( theNodeList )
> > >
> > > results in
> > >
> > > > a runtime error because the getXObjectFactory method returns a
> > > > reference
> > >
> > > to
> > >
> > > > the XObjectFactory "interface" (ie the superclass) and therein
> > >
> > > createNodeSet
> > >
> > > > is a pure virtual (ie abstract) method.
> > >
> > > That seems strange, because the same code is used in many places in
> > > Xalan-C.
> > >
> > > > In order for the appropriate XObjectFactory createNodeSet() method to
> > >
> > > get
> > >
> > > > called, the reference returned from the getXObjectFactory() method
> > > > has
> > >
> > > to be
> > >
> > > > cast to the derived XObjectFactoryDefault class which has the
> > >
> > > implemented
> > >
> > > > version of createNodeSet...
> > >
> > > Again, I find that hard to believe.  Regardless of how you cast the
> > > reference, the underlying object is the same.
> > >
> > > The main reason your approach won't work is because you are adding a
> > > reference to a stack-based object to the MutableNodeRefList instance:
> > >
> > >  theNodeList->addNode( xercesDocWrapper );
> > >
> > > That is certain to cause undefined behavior, since the object is
> > > destroyed when the block exits.
> > >
> > > What you want to do is not difficult to implement.  The main thing you
> > > need is an object to own the Xerces-C DOMDocument instance you create,
> > > along with the "node set" you want to return.  If you always return a
> > > node-set containing a single Document node, then you should do the
> > > following:
> > >
> > > 1. Create a class that derives from XNodeSetBase:
> > >
> > > #include "xercesc/dom/DOMDocument.hpp"
> > >
> > > #include "xalanc/XPath/XNodeSetBase.hpp"
> > > #include "xalanc/XPath/XNodeSetNodeProxy.hpp"
> > > #include "xalanc/XercesParserLiaison/XercesDocumentWrapper.hpp"
> > >
> > > XALAN_USING_XERCES(MemoryManager)
> > > XALAN_USING_XERCES(DOMDocument)
> > > XALAN_USING_XALAN(XNodeSetBase)
> > > XALAN_USING_XALAN(XNodeSetNodeProxy)
> > > XALAN_USING_XALAN(NodeRefListBase)
> > > XALAN_USING_XALAN(XalanNode)
> > > XALAN_USING_XALAN(XercesDocumentWrapper)
> > >
> > > class myNodeSet : public XNodeSetBase
> > > {
> > > public:
> > >
> > >     myNodeSet(
> > >         MemoryManager&  manager,
> > >         DOMDocument*    document) :
> > >         XNodeSetBase(manager),
> > >         m_wrapper(
> > >             manager,
> > >             document,
> > >             true,
> > >             true),
> > >         m_proxy(&m_wrapper)
> > >     {
> > >     }
> > >
> > >     virtual
> > >     ~myNodeSet()
> > >     {
> > >         delete m_wrapper.getXercesDocument();
> > >     }
> > >
> > >     virtual void
> > >     dereferenced()
> > >     {
> > >         delete this;
> > >     }
> > >
> > >     virtual const NodeRefListBase&
> > >     nodeset() const
> > >     {
> > >         return m_proxy.nodeset();
> > >     }
> > >
> > >     virtual XalanNode*
> > >     item(size_type      index) const
> > >     {
> > >         return m_proxy.item(index);
> > >     }
> > >
> > >     virtual size_type
> > >     getLength() const
> > >     {
> > >         return m_proxy.getLength();
> > >     }
> > >
> > > private:
> > >
> > >     XercesDocumentWrapper    m_wrapper;
> > >
> > >     // This is an existing Xalan-C class
> > >     // that "adapts" a single node, making it
> > >     // look like a node set with a single node.
> > >     const XNodeSetNodeProxy  m_proxy;
> > > };
> > >
> > > 2. In your extension function, do everything you need to create the
> > > Xerces-C DOMDocument instance.
> > >
> > > 3. Create a new instance of the class and wrap it in an XObjectPtr
> > > instance:
> > >
> > >     XObject* const   theObject = new myProxy
> > > (executionContext.getMemoryManager(), queryResultDom);
> > >
> > >     return XObjectPtr(*theObject);
> > >
> > > Note this is not necessarily compiled and tested, but it will give you
> > > an idea of what you need to do.
> > >
> > > Dave
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to