Wrong XPath evaluation with queries starting with ".//" when wrapping a Xerces
Document
---------------------------------------------------------------------------------------
Key: XALANC-596
URL: http://issues.apache.org/jira/browse/XALANC-596
Project: XalanC
Type: Bug
Components: XalanC
Versions: 1.9, 1.10
Environment: WinXP SP 2, VS .Net 2003 (7.1)
Reporter: Martin Boucher
Context :
In the following XML file, I want to select Name nodes based on this XPath
query : ".//Object/Name". The context element is the first Project element.
With XPathEvaluator::selectNodeList(), I should get a list with only one node,
I got two.
--------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-16" standalone="no" ?>
<Projects>
<Project>
<Branch>
<Object>
<Name xml:space="preserve">one</Name>
</Object>
</Branch>
</Project>
<Project>
<Branch>
<Object>
<Name xml:space="preserve">two</Name>
</Object>
</Branch>
</Project>
</Projects>
--------------------------------------------------------------------------------------
To verify my XPath expression, I've tried the sample SimpleXPathAPI with the
command line :
SimpleXPathAPI "path to the XML file" "//Project" ".//Object/Name"
It correctly output "one". The XPath expression "//Project" to obtain the
context node is evaluated with selectSingleNode. So the first Project node
matched by the query is used as the context node.
The difference between the SimpleXPathAPI sample and our code is that we used a
Xerces wrapper for the input document. I've made little changes to the sample
to obtain code that is very close to what we really do. In the sample, there is
3 steps :
1- parse a XML file (arg 1) and get a Xalan Document
2- evaluate a XPath expression (arg 2) to get the context node
3- from the context node, evaluated a XPath expression (arg 3 ) and output the
result on stdout.
I've changed these steps by :
1- parse a XML file (arg 1) and get a Xerces Document. Wrap it to get a
XalanDocument*.
2- obtain the first Project node from the Xerces Document (no need of arg 2).
Wrap this Project node to get a context in a XalanNode* interface. This step is
hardcoded to be closest of the real code we use. We already have the context
node in DOMElement* interface. If we let the step 2 of the original sample,
that is, evaluate the XPath expression (arg 2) to get the context node, that
works. Only one element Name is output.
3- this step is replaced by a "selectListNode" that should get 1 element.
Here is a code snippet of the modified sample. This code replace the sample
code from SimpleXPathAPI right after initializations.
//1- parse a XML file (arg 1) and get a Xerces Document.
const XalanDOMString theFileName(argv[1]);
LocalFileInputSource inputSrc_( theFileName.c_str() );
XercesDOMParser parser;
parser.parse( inputSrc_ );
DOMDocument* pXercesDOMDoc = parser.getDocument();
pXercesDOMDoc->normalizeDocument();
DOMElement* pDocumentElement = pXercesDOMDoc->getDocumentElement();
if( pDocumentElement == NULL )
{
return false;
}
//(1- continued) Wrap it to get a XalanDocument*.
XercesParserLiaison xercesParserLiaison;
XalanDocument* pXalanDoc = xercesParserLiaison.createDocument( pXercesDOMDoc,
false, true, true );
// 2- Get the context node. We go hardcoded way to really works on a
Xerces::DOMElement* to
// be the closest as we can of our real code. The context node we want is the
first Project element.
// We have tho skip the first child of the document element because it is a
text node (the XML is
// indented).
DOMNode* pFirstNode = pDocumentElement->getFirstChild();
pFirstNode = pFirstNode->getNextSibling();
DOMElement* pFirstProject = dynamic_cast< DOMElement* >( pFirstNode );
if( pFirstProject == NULL )
{
return 1;
}
const XMLCh *name = pFirstProject->getNodeName(); // Just to verify that name
== "Project".
// (2- continued) Wrapping this DOMElement to get a XalanNode*.
XercesDocumentWrapper* pXercesDocWrapper = dynamic_cast< XercesDocumentWrapper*
>( pXalanDoc );
assert( pXercesDocWrapper != NULL );
XercesWrapperNavigator navigator( pXercesDocWrapper );
XercesElementWrapper contextNode( pFirstProject, navigator );
XalanNode* const theContextNode = &contextNode;
XalanDocumentPrefixResolver thePrefixResolver(pXalanDoc);
// 3- Query evaluation of ".//Object/Name".
XercesDOMSupport xercesDOMSupport;
NodeRefList nodeList;
XPathEvaluator theEvaluator;
theEvaluator.selectNodeList( nodeList, xercesDOMSupport, theContextNode,
XalanDOMString(argv[3]).c_str(), thePrefixResolver );
const NodeRefList::size_type NB_ELEM = nodeList.getLength(); // BUG HERE,
receive 2 elements instead of 1.
By doing many tests, I can tell that if the XML file has, exemple, 5 Project
elements, applying the query on the first Project leads to 5 Name selected.
Applying the query on the second Project element leads to 4 Name and so on.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]