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 rc...@micron.com on 2004/10/05 22:51:10 UTC

XPathWrapper Question

Hi All,

We have a wrapper over the Xerces Library that also supports Xpath using
Xalan.  The Xpath support code that we have is taken from XPathWrapper
sample code available in the Xalan samples.  We have ran into issue with
using Xpath with nested namespaces.   The problem occurs if you have
nested namespace declarations and can be reproduced using the
XPathWrapper Sample. 

A sample XML file which causes the problem:

<rootns:root xmlns:rootns="http://root.com/rootnode/">
	<q1:foo xmlns:q1="http://q1.org/message/"/>
</rootns:root>

To reproduce the issue: Invoke XPathWrapper with the following option

C:\>XPathWrapper c:\xpathtest.xml / /rootns:root:/q1:foo

The sample works if the namespace declaration for q1 is moved to the
root node.  However, we cannot change the declaration.  The issue
occurs in the execute statement in the code.  

For sake of completeness, here is snippet of sample code that I used to
convert from Xerces to Xalan DOM and call Xpath to reproduce the
problem.  Like I mentioned earlier, the problem can be reproduced using
the XpathWrapper sample also.   I can post the whole source code if
anyone is interested.  The error I get in my sample is

Prefix must resolve to a namespace: q1.
expression = '/rootns:root/q1:foo' Remaining tokens are:  ('/' 'rootns'
':' 'root' '/')

Is this the right way to call Xpath queries on Xerces DOM objects?  What
do I need to change to fix the issue? Any suggestions will be greatly
appreciated. 

Thanks,

Ravin

///////////From
mySample.cpp////////////////////////////////////////////////////////////
////////////////
////////////////////////////////////////////////////////////////////////
/////////////////////////////////////
DOMNode *gDOMNode;

//Node is populated using MemBufInputSource()


DOMDocument* xercesDocument = NULL;
if( gDOMNode->getNodeType() != 9 /*DOCUMENT_NODE*/ )
{
    xercesDocument = gDOMNode->getOwnerDocument();
}
else
{
    xercesDocument = (DOMDocument*)gDOMNode;
}

if( NULL == xercesDocument )
{
    wcout <<  L"Document node is NULL." << endl;
}
		
XercesDOMSupport theDOMSupport;
XercesDocumentWrapper theWrapper(xercesDocument, false, false);

// Initialize the XPath subsystem
static XPathInit theInit;

// configure the objects needed for XPath to work with the Xerces DOM
XPathEnvSupportDefault			theEnvSupport;
XObjectFactoryDefault			theXObjectFactory;
XPathExecutionContextDefault	theExecutionContext(theEnvSupport,
theDOMSupport, theXObjectFactory);
XPathFactoryDefault				theXPathFactory;
XPathProcessorImpl				theXPathProcessor;
		
XalanElement*	rootElem = theWrapper.getDocumentElement();
XalanNode*	currentNode = theWrapper.mapNode(gDOMNode);
		
// first get the context nodeset
XPath* const contextXPath = theXPathFactory.create(); //will be deleted
by theXPathFactory destructor
XPathConstructionContextDefault		theXPathConstructionContext;


theXPathProcessor.initXPath(*contextXPath, 
            theXPathConstructionContext,
			XalanDOMString(strQuery.c_str()), 
			ElementPrefixResolverProxy(rootElem,
theEnvSupport, theDOMSupport));
		
XObjectPtr	xObj = contextXPath->execute(currentNode,
			ElementPrefixResolverProxy(rootElem,
theEnvSupport, theDOMSupport),
			theExecutionContext);

Re: XPathWrapper Question

Posted by da...@us.ibm.com.
> C:\>XPathWrapper c:\xpathtest.xml / /rootns:root:/q1:foo 
> The sample works if the namespace declaration for q1 is moved to the 
root node.
> However, we cannot change the declaration.  The issue  occurs in the 
execute
> statement in the code. 

XPathWrapper is meant as a demonstration sample, not as production code. 
It has the limitation that any namespace bindings you use must be declared 
on the document element.

> theXPathProcessor.initXPath(*contextXPath, 
>             theXPathConstructionContext, 
>                         XalanDOMString(strQuery.c_str()), 
>                         ElementPrefixResolverProxy(rootElem, 
theEnvSupport, theDOMSupport)); 
> 
> XObjectPtr      xObj = contextXPath->execute(currentNode, 
>                         ElementPrefixResolverProxy(rootElem, 
theEnvSupport, theDOMSupport), 
>                         theExecutionContext); 

You do exactly what XPathWrapper does -- you create an 
ElementPrefixResolverProxy and give it the document element.  So, the only 
namespace bindings available are those declared on that element.

What you need is another implementation of the PrefixResolver abstract 
base class that knows about the prefixes and namespace URIs you are 
interested in.  You can implement your own, or you can use an instance of 
XalanDocumentPrefixResolver, if you want to make all of the namespace 
bindings in the entire document available.  Beware, however, that this is 
less efficient than creating your own PrefixResolver that only knows about 
the prefixes you are interested in.  Also, XalanDocumentPrefixResolver 
does not work well when a document contains multiple namespace 
declarations for the same prefix, but with different namespace URIs.

Dave