[prev in list] [next in list] [prev in thread] [next in thread] 

List:       xalan-dev
Subject:    [jira] Created: (XALANC-596) Wrong XPath evaluation with queries
From:       "Martin Boucher (JIRA)" <xalan-dev () xml ! apache ! org>
Date:       2006-01-26 20:45:11
Message-ID: 1355091616.1138308311694.JavaMail.jira () ajax ! apache ! org
[Download RAW message or body]

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: xalan-dev-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-dev-help@xml.apache.org


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic