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