Thank you, thank you, thank you!  Your assistance cleared up the problem
I was having and is very much appreciated.

As a Xalan newbie, what resources are available to come up to speed on
Xalan's XPath API?  The 2 sample applications that come with Xalan
(SimpleXPathAPI and SimpleXPathCAPI) are useful, but limited (I was
stuck on how to use the results from one query as a context to delve
deeper into the XML).  Also, there is the email archive to search
through.  But in terms of using the Xalan API for XPath, are there any
additional resources?

Many, many thanks!

John P. Wilson
Creare Inc.
P.O. Box 71
Hanover, NH 03755
603-640-2474
Fax 603-643-4657
 
-----Original Message-----
From: David Bertoni [mailto:[EMAIL PROTECTED] 
Sent: Wednesday, October 31, 2007 2:10 AM
To: xalan-c-users@xml.apache.org
Subject: Re: XPath: Querying for a node's children

John P. Wilson wrote:
> I have the following type of XML:
> 
>  
...
>  
> 
> I want to be able to get a list of the "ns1:pinchpoint" nodes, and
then 
> step through each node in the list and extract the boundingCylinder1, 
> boundingCylinder2, location, and flow/resistance or flow/closure data.

> I have been able to get the list of pinchpoint nodes, and then I can 
> extract **one** of the desired sub-nodes (such as boundingCylinder1), 
> but I can not then extract the other child nodes.  Here is my code:
> 
>  
> 
> XMLPlatformUtils::Initialize();
> 
>       XPathEvaluator::initialize();
> 
>       XercesDOMParser *parser = new XercesDOMParser;
> 
>       parser->setDoNamespaces(true);
> 
>       parser->setDoSchema(true);
> 
>       parser->setValidationSchemaFullChecking(true);
> 
>       parser->setCreateEntityReferenceNodes(true);
> 
>       DOMDocument *doc = 0;
> 
>       parser->parse(argv[1]);
> 
>       doc = parser->getDocument();
> 
>       // The XPath expression to evaluate
> 
>       std::string xpath =
"/ns1:IPEModelInput/ns1:system/ns1:pinchpoint";
...
>       NodeRefList nodelist;
> 
>       evaluator.selectNodeList(
>             nodelist,
>             dom_support,
>             root_context_node,
>             expression.c_str(),
>             namespace_node);
> 
>       NodeRefList::size_type length = nodelist.getLength();
> 
>       cout << "number of nodes = " << length << endl;
> 
>       for (unsigned int i = 0; i < nodelist.getLength(); ++i) {
> 
>             // Get this pinchpoint node
> 
>             char newxpath[1024];
> 
>             sprintf(newxpath,"%s[%d]",xpath.c_str(),i+1);
I don't know you've decided execute another XPath expression here.  You 
seem to want to select each node in the nodeset individually, but that's

not what you're doing.  You need to understand the semantics of
positional 
predicates, but that's beyond the scope of this list.

Since you've already selected all of the ns1:pinchpoint children,
all you need to do is to iterate them, and your loop is doing just that.

> 
>             XalanDOMString newexpression(newxpath);
>             cout << "pinchpoint path = " << newxpath << endl;
>             XalanNode* node = nodelist.item(i);
>             XalanNode* const theContextNode =
>                   evaluator.selectSingleNode(
>                         dom_support,
>                         node,
>                         newexpression.c_str(),
>                         namespace_node);
Instead of evaluating this XPath expression, you can simply use "node"
as 
the context node for the following expressions.

> 
>             // Get the location - THIS WORKS
> XalanDOMString locationDOMStr("ns1:location");
> 
>             const XObjectPtr locationResult(
>                   evaluator.evaluate(
>                         dom_support,
>                         theContextNode,
>                         locationDOMStr.c_str(),
>                         namespace_node));
> 
>             assert(locationResult.null() == false);
> 
>             cout << "The location = "
>                    << locationResult->str()
>                    << endl;
> 
>             // Get the first bounding cylinder - THIS DOESN'T WORK
>             XalanDOMString boundaryDOMStr("ns1:boundingCylinder1");
> 
>             const XObjectPtr boundaryResult(
>                   evaluator.evaluate(
>                         dom_support,
>                         theContextNode,
>                         boundaryDOMStr.c_str(),
>                         namespace_node));
> 
>             assert(boundaryResult.null() == false);
> 
>             cout << "Boundary 1 = "
>                    << boundaryResult->str()
>                    << endl;
>       }
> 
>  
> 
> The "assert" before I print boundaryResult is always thrown.
No, it's different assert.  You've not read the documentation for the 
function you're calling, and as a result, you're violating one of its 
preconditions.  Here is the excerpt from the header file:

/**
  * Evaluate the supplied XPath expression, within the given context.
The
  * result is returned as a generalized object.  The object will be
  * destroyed when the user's copy of the returned XObjectPtr goes out
of
  * scope, or when the XPathEvaluator goes out of scope or another
expression
  * is evaluated.
  *
  * The user's XObjectPtr copy _must_ no longer be in scope when the 
XPathEvaluator
  * instance goes out of scope, or another expression is evaluated.

Note that you must ensure the XObjectPtr instance is destroyed before
you 
call evaluate() again.

> 
> How do I step through each "pinchpoint" object and extract the data?

Use extra scope to insure that all of your previous result objects have 
been destroyed, or use selectNodeList, instead of evaluate(), just as
you 
did when you selected the ns1:pinchpoint elements.  As a quick fix for
your 
code, I did the following:

         {
             const XObjectPtr locationResult(
                   evaluator.evaluate(
                         dom_support,
                         node,
                         locationDOMStr.c_str(),
                         namespace_node));

             assert(locationResult.null() == false);

             cout << "The location = "
                    << locationResult->str()
                    << endl;
         }


         // Get the first bounding cylinder - THIS DOESN'T WORK

         XalanDOMString boundaryDOMStr("ns1:boundingCylinder1");

         {
             const XObjectPtr boundaryResult(
                   evaluator.evaluate(
                         dom_support,
                         node,
                         boundaryDOMStr.c_str(),
                         namespace_node));

             assert(boundaryResult.null() == false);

             cout << "Boundary 1 = "
                    << boundaryResult->str()
                    << endl;
         }

Dave

Reply via email to