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]