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