Hi David,

I got it. XMLParserLiaison was the culprit. I made it a class member and it
worked. 
Interestingly, previously I tried the same with every other variable except
this :-( Anyway, thanks for your tips. BTW, how long a brand new Xalan
member is allowed to make such silly mistakes :-)

Thanks again
Mayank


-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] 
Sent: Friday, June 20, 2003 1:31 PM
To: 'xalan-c-users@xml.apache.org'
Subject: RE: XalanNode.cloneNode() issue !!






Hi Mayank,

The problem is you are initializing and shutting down Xalan in the stack
frame of the query() function.  You cannot do this, because when you shut
down Xalan, you cannot have any existing Xalan objects.

If query() is a member of a class, you can make some of these objects data
members.  You will need to understand the lifetimes of the various objects
so you know what you must keep as an instance member and what you can create
on the stack frame.

Some suggestions:

   1. Initialize the Xalan subsystem once when your program starts and
   terminate it once when your program ends.  This is more efficient and is
   thread-safe.

   2. If you want the XalanDocument instance to have a lifetime greater
   than that of the function call you must make sure the
   XalanSourceTreeParserLiaison instance has a lifetime at least as great
   as that of the collection of nodes you are returning.  You could make
   this a member of a class, if this function is a class member, or you
   could pass it into the function call.  If you read the document for
   XMLParserLiaison::parseXMLStream() you will see the following:

       "The liaison owns the XalanDocument instance, and will delete it when
when asked (see DestroyDocument()), or when the liaison is reset, or goes
out of scope."

   There are other ways you can create an instance of Xalan's source tree
   implementation, but, if you do that, you will be responsible for
   deleting it, so I don't recommend you do so.

Xalan-C has a very consistent practice of maintaining ownership of objects.
This makes this slightly more complicated, but protects against memory
leaks, because dynamically created objects tend to be owned and managed by
other objects.

Dave



|---------+--------------------------->
|         |           "KHARE,MAYANK   |
|         |           (HP-India,ex2)" |
|         |           <[EMAIL PROTECTED]|
|         |           .com>           |
|         |                           |
|         |           06/20/2003 11:15|
|         |           AM              |
|---------+--------------------------->
 
>---------------------------------------------------------------------------
------------------------------------|
  |
|
  |        To:      "'xalan-c-users@xml.apache.org'"
<xalan-c-users@xml.apache.org>                               |
  |        cc:      (bcc: David N Bertoni/Cambridge/IBM)
|
  |        Subject: RE: XalanNode.cloneNode() issue !!
|
 
>---------------------------------------------------------------------------
------------------------------------|




Hi David

Thanks for your response and time. Pl. see my comments inline.

David :
>Cloning is almost never necessary, nor ever efficient.  The pointers
returned in the XObject are pointers into your
>instance document, so as long as that is in scope, all you have to do
>is
copy the pointers to your own data structure.

Mayank:
I tried that(copying pointers) but did't work. That's why turned to cloning
as a last resort. Outside query(), pointers returned in the XObject pointer
becoming invalid. I also tried making a copy of Xobjectptr itself(by
assingning it to a global XObjectPtr hoping that this will increase the
reference count of original XOjectPtr and hence increase the lifecycle of
it), but got an assertion in ~XalanReferenceCountedObject().

David:
>Are you using the default implementation of Xalan's source tree, or are
you
wrapping the Xerces DOM for these XPath
>searches? The general rule is if you're going to modify the DOM 
>instance,
you should use the Xerces DOM and wrap it for
>Xalan.

Mayank:
I don't want to modify DOM instance hence am using Xalan all the way.

David:
>Please provide a _small_ snippet of code which shows how your are 
>building
the tree and how you do the XPath query.

Mayank:
Pl. have a look below.

QueryResult query(const char*        xml, const char* context, const char*
expr,ostream& errorStream)
{
                       QueryResult L_resultSet;

                // Initialize the XPath subsystem...
                XPathInit
theInit;
                XalanSourceTreeDOMSupport                    theDOMSupport;
                XalanSourceTreeParserLiaison theLiaison(theDOMSupport);
                theDOMSupport.setParserLiaison(&theLiaison);
                XalanElement*        rootElem = 0;
                try
                {
                    XALAN_USING_XERCES(MemBufInputSource)
                    // parse XML and get root element
                    MemBufInputSource            inStream((XMLByte*)xml,
strlen(xml),
"foo", false);
                    XalanDocument* const         doc =
theLiaison.parseXMLStream(inStream);
                    assert(doc != 0);
                    rootElem = doc->getDocumentElement();
                    assert(rootElem != 0);
                }
                catch(...){}

                XPathEnvSupportDefault
theEnvSupport;
                XObjectFactoryDefault
theXObjectFactory;
                XPathExecutionContextDefault
theExecutionContext(theEnvSupport, theDOMSupport, theXObjectFactory);
                XPathConstructionContextDefault theXPathConstructionContext;
                XPathFactoryDefault
theXPathFactory;
                XPathProcessorImpl
theXPathProcessor;

                try
                {
                    XPath* const           contextXPath =
theXPathFactory.create();
                    theXPathProcessor.initXPath(*contextXPath,
                        theXPathConstructionContext,
                        XalanDOMString(context),
                        ElementPrefixResolverProxy(rootElem, theEnvSupport,
theDOMSupport));
                    XObjectPtr             xObj =
                        contextXPath->execute(rootElem,
                        ElementPrefixResolverProxy(rootElem, theEnvSupport,
theDOMSupport),
                        theExecutionContext);
                    const NodeRefListBase&             contextNodeList =
xObj->nodeset();
                    const unsigned int           theLength =
                         contextNodeList.getLength();

                    XPath* const           xpath =
theXPathFactory.create();
                        theXPathProcessor.initXPath(*xpath,
                            theXPathConstructionContext,
                            TranscodeFromLocalCodePage(expr),
                            ElementPrefixResolverProxy(rootElem,
theEnvSupport, theDOMSupport));

                   xObj = xpath->execute(contextNodeList.item(0),
                            ElementPrefixResolverProxy(rootElem,
theEnvSupport, theDOMSupport),
                            theExecutionContext);

                                      // This will store the address of
XObjectPtr in QueryResult class.
                                      // Can't pass reference here as
Copying is not allowed. (~XalanReferenceCountedObject() will give
                                      // assertion failure).
                   L_resultSet.setConfigNode(&xObj);

                                      // This will extract the Nodeset from
Xobjectptr and then clone each individual XalanNode
                                      // and store the CLONED XalanNodes to
a vector
                   L_resultSet.cloneXalanNodes();

                                      // Everything in L_resultSet works
fine till here. Once this function return QueryResult CLONED nodes
                   // inside L_resultSet will become invalid.
                                      return L_resultSet;
}

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
Sent: Friday, June 20, 2003 9:14 AM
To: 'xalan-c-users@xml.apache.org'
Subject: Re: XalanNode.cloneNode() issue !!






> I'm new to XSL and related technologies. Was trying my hands on Xalan 
> 1.5 library for C++ and faced the following issue:
>
> Actually I tried to perform a Xpath query on a XML document. Xpath 
> Query
is
> working fine. The problem is to encapsulate the query
> result(XObjectPtr) into my own class to use it somewhere else later 
> on. I've got a cloning method in my QueryResult wrapper class(see 
> attached code snippet below)
to
> clone all the XalanNodes which are available via XObjectPtr just after
the
> successful query(witin the scope of MyXPathQuery::query function). I'm 
> opting for cloning becoz as the XObjectPtr will go out of scope it's 
> reference count would be reduced to 0 and it will become invalid. I 
> tried making a copy of XObjectPtr(by assingment operator) returned by 
> the query but Xalan library is throwing an assertion immediately when
> query()
function
> is exiting and this is happening when XObjectPtr is getting deleted. 
> (In ~XalanReferenceCountedObject()). According to my understanding it 
> sud't happen.

Cloning is almost never necessary, nor ever efficient.  The pointers
returned in the XObject are pointers into your instance document, so as long
as that is in scope, all you have to do is copy the pointers to your own
data structure.  Are you using the default implementation of Xalan's source
tree, or are you wrapping the Xerces DOM for these XPath searches? The
general rule is if you're going to modify the DOM instance, you should use
the Xerces DOM and wrap it for Xalan.  If you're not going to modify the
DOM, and you're just parsing a stream of XML to create it, use Xalan's
default source tree.

If you are wrapping the Xerces DOM, you need to recover the original Xerces
DOM nodes from the Xalan wrapper nodes.  Please provide a _small_ snippet of
code which shows how your are building the tree and how you do the XPath
query.  There are member functions provided to map Xalan nodes to Xerces
nodes so you can do this.

> Deep Cloning works fine as long as I'm using the cloned object till
original
> Xpointer object is valid. After original Xpointer object 
> dies(immediately after MyXPathQuery::query exited) all the string 
> based data in CLONED XalanNodes becomes invalid (all attribute/element 
> values and names). This
is
> happening inspite of DEEP CLONING.

What is this Xpointer object you're talking about?  We don't have a class by
that name in Xalan-C.  As I said before, cloning is rarely necessary, and
it's irrelevant whether or not you're using deep cloning.

>        if( (*m_xObjectPtr)->getType() == XObject::eTypeNodeSet )

XObjectPtr has its own operator->() defined, so you can just do this:

   if( m_xObjectPtr->getType() == XObject::eTypeNodeSet )

Dave

Reply via email to