You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xalan.apache.org by Mark Biamonte <Ma...@merant.com> on 2001/01/29 19:16:06 UTC
XPath parser and names with leading underscore
The XPath Parser has problems with node names that begin with a leading
underscore.
Given the following XML
<CTABLE>
<_Record>
<CHARCOL>bc</CHARCOL>
</_Record>
<_Record>
<CHARCOL>cde</CHARCOL>
</_Record>
</CTABLE>
I try to execute the following (where m_XmlDocument contains the above XML)
XPathAPI xpathParser = new XPathAPI();
NodeList m_Rows = xpathParser.selectNodeList(m_XmlDocument,
"/CTABLE/_Record");
selectNodeList throws an exception with the message
Extra illegal tokens:'_Record'
I am able to work around the problem if use the following expression instead
NodeList m_Rows = xpathParser.selectNodeList(m_XmlDocument,
"/CTABLE/*[local-name()='_Record']");
Per the XML 1.0 Specification the underscore character is one of the few non
letter characters that an XML tag name can begin with. The name production
from the XML Spec is
Name ::= (Letter | '_' | ':') (NameChar)*
I have traced the problem down to the Step function in XPathParser.java. At
the bottom of the function is an else if statement that checks to see if the
first letter of the token is a letter as indicated below. In the case of a
tag name that begins with an underscore, this test fails and the basics
function is not called and processing of the expression basically stops
there.
I am using the xalan-java version 2.0.D07 drop.
XPathParser.java
=================================================
...
protected void Step() throws javax.xml.transform.TransformerException
{
int opPos = m_ops.m_opMap[OpMap.MAPINDEX_LENGTH];
if (tokenIs("."))
{
...
}
else if (tokenIs(".."))
{
...
}
// There is probably a better way to test for this
// transition... but it gets real hairy if you try
// to do it in basis().
else if (tokenIs('*') || tokenIs( '@' <mailto:'@'> ) || tokenIs('/')
<======== Problem here?
|| Character.isLetter(m_token.charAt(0)))
{
Basis();
while (tokenIs('['))
{
Predicate();
}
// Tell how long the entire step is.
m_ops.m_opMap[opPos + OpMap.MAPINDEX_LENGTH] =
m_ops.m_opMap[OpMap.MAPINDEX_LENGTH] - opPos;
}
}
...
-------------------------
Mark Biamonte
Morrisville Office
(919) 461-4354
Mark.Biamonte@merant.com