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]