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