You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-users@xalan.apache.org by Smeeta Jalan <sm...@gmail.com> on 2006/04/24 10:03:12 UTC

Regarding XPath query

Hi,

I am using Xalan-C 1.10 and Xerces 2.7. I have to write a wrapper
class whose functions gives me the results of XPath queries.
I got an example in the samples SimpleXPathAPI which serves my
purpose. But I have few problems. I wanted to  split the entire thing
into 2 functions so that the instance of XalanDocument gets created
only once.
I have a private function which returns me the xalan_document and
another public function which should give me the result of an XPath
query. (XPath query being the parameter of the function).

I am pasting the sample of my code to give you idea, but this doesn't
work.It gives me a run time error at this line:
XalanDocumentPrefixResolver	thePrefixResolver(xalan_document);
saying some access violation reading some location.

int MyClass::create_xalan_document(unsigned short* filename) {

	// Initialize the XalanSourceTree subsystem...
	XalanSourceTreeInit	theSourceTreeInit;

	// We'll use these to parse the XML file.
  	XalanSourceTreeParserLiaison theLiaison(theDOMSupport);

	// Hook the two together...
	theDOMSupport.setParserLiaison(&theLiaison);

	const XalanDOMString theFileName(filename);

	// Create an input source that represents a local file...
	const LocalFileInputSource theInputSource(theFileName.c_str());

  	// Parse the document...
	xalan_document = theLiaison.parseXMLStream(theInputSource);
	assert(xalan_document != 0);
  return 1;
}

int MyClass::EvaluateXPathExpression (unsigned short *xpath) {

  assert(xalan_document != 0);
  XalanDocumentPrefixResolver	thePrefixResolver(xalan_document);

	XPathEvaluator theEvaluator;

	// OK, let's find the context node...
	XalanNode* const	theContextNode = theEvaluator.selectSingleNode(
      theDOMSupport,
			xalan_document,
			XalanDOMString("/").c_str(),
			thePrefixResolver);

  if (theContextNode == 0) {
    wprintf (L"No nodes matched the location path");
    return TAU_FAILURE;
  }
	else {

	  // OK, let's evaluate the expression...
		const XObjectPtr	theResult( theEvaluator.evaluate( theDOMSupport,
          theContextNode,
          XalanDOMString(xpath).c_str(),
	  thePrefixResolver));
    assert(theResult.null() == false);
    cout<<theResult->str();
    return 1;
		
	}
}

I have these
xalanc_1_10::XalanDocument* xalan_document;
xalanc_1_10::XalanSourceTreeDOMSupport theDOMSupport;
as private members of my class.

Can you tell me where am I going wrong?
I couldn't make out things very well from the documentation available.

I also tried initializing XalanSourceTreeInit in a main function
called before these two but it doesn't help.

Thanks in advance,
Smeeta

Re: Regarding XPath query

Posted by Smeeta Jalan <sm...@gmail.com>.
Hey,

Thanks a lot for the answer. The initial query is resolved but I am stuck
with one more problem.

So, now my wrapper class has these 3 functions. I intend to differentiate
the XPath which returns a string or an array of strings with those which
returns Xalan Node or array of XalanNodes. So, I have split these into 2
functions. The first one works fine for me but the second one gives me error
in the constructor of XercesDocumentWrapper class.I intend to return
DOMNode* or a vector of DOMNode* from this function. For this, I have to
convert XalanNode to DOMNode. I have used XercesDocumentWrapper class for
this. I am trying to pass the instance of DOMDocument created using
DOMBuilder its constructor but it gives me error.
I followed the thread for doing so:

http://marc.theaimsgroup.com/?l=xalan-c-users&m=105887947932408&w=2

Please can you figure out the problem? I have seen more queries on this but
didn't get the answer.

Thanks,
Smeeta


int MyClass::create_xalan_document(wchar_t *filename) {

  // Initialize the XalanSourceTree subsystem...
    //XalanSourceTreeInit    theSourceTreeInit;

    // use these to parse the XML file.
  // check this
  //XalanSourceTreeParserLiaison theLiaison(theDOMSupport);

  //XalanSourceTreeParserLiaison theLiaison;


    // Hook the two together...
    theDOMSupport.setParserLiaison(&theLiaison);

    const XalanDOMString theFileName(filename);

    // Create an input source that represents a local file...
    const LocalFileInputSource theInputSource(theFileName.c_str());

  // Parse the document...
    xalan_document = theLiaison.parseXMLStream(theInputSource);
    assert(xalan_document != 0);
  return 1;
}

int MyClass::EvaluateXPathExpression (wchar_t *xpath, wchar_t **outstring,
vector<wchar_t*> **outarrayofstrings, wchar_t *contextnode) {


  XalanDocumentPrefixResolver    thePrefixResolver(xalan_document);
    XPathEvaluator theEvaluator;

    // find the context node...

    XalanNode* const    theContextNode = theEvaluator.selectSingleNode (
      theDOMSupport,
            xalan_document,
            XalanDOMString(contextnode).c_str(),

            thePrefixResolver);
  if (theContextNode == 0) {
    wprintf (L"No nodes matched the location path");
    return -1;
  }
    else {
    // evaluate the expression...

        const XObjectPtr    theResult( theEvaluator.evaluate( theDOMSupport,
          theContextNode,
          XalanDOMString(xpath).c_str(),
                    thePrefixResolver));
    const NodeRefListBase& nodeset = theResult->nodeset();

    //Iterate through the node list
    size_t len =  nodeset.getLength();
    if (len <= 0) {
      return -1;
    }
    else if (len == 1) {
      if(IsBadWritePtr (outstring, sizeof(outstring))) {
        return -1;
      }
      wcscpy (*outstring, const_cast<wchar_t
*>(nodeset.item(0)->getNodeValue().c_str()));
      return 1;
    }
    else {
      if(IsBadWritePtr (outarrayofstrings, sizeof(outarrayofstrings))) {
        return -1;
      }
      for (size_t i=0; i < len; ++i) {
        (*outarrayofstrings)->push_back(const_cast<wchar_t *>(
                nodeset.item(i)->getNodeValue().c_str()));
      }
      return 2;
    }
  }
}

int MyClass::EvaluateXPathNode (wchar_t *xpath, DOMNode **outnode,
vector<DOMNode*> **outarrayofnodes, wchar_t *contextnode) {


  XalanDocumentPrefixResolver    thePrefixResolver(xalan_document);
    XPathEvaluator theEvaluator;

    // find the context node...

    XalanNode* const    theContextNode = theEvaluator.selectSingleNode (
      theDOMSupport,
            xalan_document,
            XalanDOMString(contextnode).c_str(),

            thePrefixResolver);
  if (theContextNode == 0) {
    wprintf (L"No nodes matched the location path");
    return -1;
  }
    else {
    // evaluate the expression...
    NodeRefList theResult;
        theResult = theEvaluator.selectNodeList( theResult,

        theDOMSupport,
        theContextNode,
        XalanDOMString(xpath).c_str(),
        thePrefixResolver);

     XercesDocumentWrapper theWrapper(dom_document_, false, false, false);
//dom_document_ is an instance of DOMDocument created using Xerces
DOMBuilder

    //Iterate through the node list
    size_t len =  theResult.getLength();
    if (len <= 0) {
      return -1;
    }
    else if (len == 1) {
      if(IsBadWritePtr (outnode, sizeof(outnode))) {
        return -1;
      }

       *outnode = (DOMNode *)(theWrapper.mapNode(theResult.item(0)));
      return 1;
    }
    else {
      if(IsBadWritePtr (outarrayofnodes, sizeof(outarrayofnodes))) {
        return -1;
      }
      for (size_t i=0; i < len; ++i) {

        (*outarrayofnodes)->push_back((DOMNode *)(theWrapper->mapNode(
                theResult.item(i))));
      }
      return 2;
    }
  }
}


On 4/24/06, David Bertoni <db...@apache.org> wrote:
>
> Smeeta Jalan wrote:
> > Hi,
> >
> > I am using Xalan-C 1.10 and Xerces 2.7. I have to write a wrapper
> > class whose functions gives me the results of XPath queries.
> > I got an example in the samples SimpleXPathAPI which serves my
> > purpose. But I have few problems. I wanted to  split the entire thing
> > into 2 functions so that the instance of XalanDocument gets created
> > only once.
> > I have a private function which returns me the xalan_document and
> > another public function which should give me the result of an XPath
> > query. (XPath query being the parameter of the function).
> >
> > I am pasting the sample of my code to give you idea, but this doesn't
> > work.It gives me a run time error at this line:
> > XalanDocumentPrefixResolver   thePrefixResolver(xalan_document);
> > saying some access violation reading some location.
> >
> > int MyClass::create_xalan_document(unsigned short* filename) {
> >
> >       // Initialize the XalanSourceTree subsystem...
> >       XalanSourceTreeInit     theSourceTreeInit;
> >
> >       // We'll use these to parse the XML file.
> >       XalanSourceTreeParserLiaison theLiaison(theDOMSupport);
> >
> >       // Hook the two together...
> >       theDOMSupport.setParserLiaison(&theLiaison);
> >
> >       const XalanDOMString theFileName(filename);
> >
> >       // Create an input source that represents a local file...
> >       const LocalFileInputSource theInputSource(theFileName.c_str());
> >
> >       // Parse the document...
> >       xalan_document = theLiaison.parseXMLStream(theInputSource);
> >       assert(xalan_document != 0);
> >   return 1;
> > }
> >
>
> The documentation for XMLParserLiaison::parseXMLStream() says the
> following:
>
> /**
>   * Parse the text pointed at by the reader as XML, and return a DOM
>   * Document interface.  It is recommended that you pass in some sort of
>   * recognizable name, such as the filename or URI, with which the reader
>   * can be recognized if the parse fails.
>   *
>   * 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.
>   *
>   * @param reader     stream that should hold valid XML
>   * @param identifier used for diagnostic purposes only, some sort of
>   *                   identification for error reporting, default an empty
>   *                   string
>   * @return DOM document created
>   */
>
> So, the XalanDocument instance is being destroyed when the
> XalanSourceTreeParserLiaison you create on the stack in your function is
> destroyed.  That happens when the function exits.
>
> If you really want to wrap these calls in your class, then make that
> instance, and the XalanSourceTreeDOMSupport instance it needs members of
> your class.
>
> Note that it's not generally a good idea to use the "Init" class in your
> code.  The best thing to do is to call XalanTransformer::initialize()
> right after you call PlatformUtils::Initialize(), when your application
> starts.
>
>
> ...
>
>
> > Can you tell me where am I going wrong?
> > I couldn't make out things very well from the documentation available.
> >
> > I also tried initializing XalanSourceTreeInit in a main function
> > called before these two but it doesn't help.
>
> As I said previously, the best thing to do is to call
> XalanTransformer::initialize() in main(), and remove any usage of the
> "Init" classes.
>
> >
> > Thanks in advance,
> > Smeeta
> >
>
> Dave
>

Re: Regarding XPath query

Posted by David Bertoni <db...@apache.org>.
Smeeta Jalan wrote:
> Hi,
> 
> I am using Xalan-C 1.10 and Xerces 2.7. I have to write a wrapper
> class whose functions gives me the results of XPath queries.
> I got an example in the samples SimpleXPathAPI which serves my
> purpose. But I have few problems. I wanted to  split the entire thing
> into 2 functions so that the instance of XalanDocument gets created
> only once.
> I have a private function which returns me the xalan_document and
> another public function which should give me the result of an XPath
> query. (XPath query being the parameter of the function).
> 
> I am pasting the sample of my code to give you idea, but this doesn't
> work.It gives me a run time error at this line:
> XalanDocumentPrefixResolver	thePrefixResolver(xalan_document);
> saying some access violation reading some location.
> 
> int MyClass::create_xalan_document(unsigned short* filename) {
> 
> 	// Initialize the XalanSourceTree subsystem...
> 	XalanSourceTreeInit	theSourceTreeInit;
> 
> 	// We'll use these to parse the XML file.
>   	XalanSourceTreeParserLiaison theLiaison(theDOMSupport);
> 
> 	// Hook the two together...
> 	theDOMSupport.setParserLiaison(&theLiaison);
> 
> 	const XalanDOMString theFileName(filename);
> 
> 	// Create an input source that represents a local file...
> 	const LocalFileInputSource theInputSource(theFileName.c_str());
> 
>   	// Parse the document...
> 	xalan_document = theLiaison.parseXMLStream(theInputSource);
> 	assert(xalan_document != 0);
>   return 1;
> }
> 

The documentation for XMLParserLiaison::parseXMLStream() says the following:

/**
  * Parse the text pointed at by the reader as XML, and return a DOM
  * Document interface.  It is recommended that you pass in some sort of
  * recognizable name, such as the filename or URI, with which the reader
  * can be recognized if the parse fails.
  *
  * 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.
  *
  * @param reader     stream that should hold valid XML
  * @param identifier used for diagnostic purposes only, some sort of
  *                   identification for error reporting, default an empty
  *                   string
  * @return DOM document created
  */

So, the XalanDocument instance is being destroyed when the 
XalanSourceTreeParserLiaison you create on the stack in your function is 
destroyed.  That happens when the function exits.

If you really want to wrap these calls in your class, then make that 
instance, and the XalanSourceTreeDOMSupport instance it needs members of 
your class.

Note that it's not generally a good idea to use the "Init" class in your 
code.  The best thing to do is to call XalanTransformer::initialize() 
right after you call PlatformUtils::Initialize(), when your application 
starts.


...


> Can you tell me where am I going wrong?
> I couldn't make out things very well from the documentation available.
> 
> I also tried initializing XalanSourceTreeInit in a main function
> called before these two but it doesn't help.

As I said previously, the best thing to do is to call 
XalanTransformer::initialize() in main(), and remove any usage of the 
"Init" classes.

> 
> Thanks in advance,
> Smeeta
> 

Dave