Fix keywords not recognized as NCNames in QNames#142
Merged
faassen merged 1 commit intoPaligo:mainfrom Mar 20, 2026
Merged
Conversation
Token::ncname() only included reserved function names (XPath 3.1 A.3) but omitted axis names and other keywords. This caused the lexer to fail combining tokens like `ex:child` into a PrefixedQName, since Token::Child.ncname() returned None. Per the spec: "Keywords in XPath 3.1 [...] are not reserved—that is, names in XPath 3.1 expressions are allowed to be the same as language keywords." Add all keyword tokens to Token::ncname() to match what the parser-level parser_keyword() already handles. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Collaborator
|
Thank you! It interested me to see whether any of the XPath tests caught this one, but there were no tests of that nature! |
faassen
approved these changes
Mar 20, 2026
Open
Contributor
Author
|
Thank you for merging this so quickly. What's your bugfix release schedule policy – when do you think this can hit crates.io? 🙏 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
XPath expressions using qualified names where the local name is a keyword fail to parse. For example, given this XML:
The XPath
//ex:child/string()fails because the lexer doesn't combineNCName("ex")+Colon+Childinto a singlePrefixedQNametoken. This affects all axis names (child,parent,self,ancestor,descendant,following,preceding,namespace, and their compound forms) as well as other keywords (and,or,div,mod,for,let, etc.) when used as the local name in a prefixed QName.Unprefixed usage (e.g.
//childas an element name) is not affected — the parser-levelparser_keyword()already handles that correctly. A test is included to confirm this.Validation with Saxon HE 12.9
All expressions return the expected results:
Root cause
Token::ncname()inxee-xpath-lexer/src/reserved.rsonly listed the reserved function names from XPath 3.1 spec section A.3 (likemap,array,function,if, etc.) but omitted axis names and other keywords. TheExplicitWhitespaceiterator calls this method to decide whether a token after a:can form part of aPrefixedQName. Since e.g.Token::Child.ncname()returnedNone, the combination failed.Per the XPath 3.1 spec:
Fix
Add all keyword tokens to
Token::ncname()to match what the parser-levelparser_keyword()already handles. This makes the lexer correctly combine e.g.NCName("ex")+Colon+ChildintoPrefixedQName { prefix: "ex", local_name: "child" }.Tests
Lexer-level (
xee-xpath-lexer/src/explicit_whitespace.rs):test_prefixed_qname_with_axis_name_local_names— all 13 axis names as local namestest_prefixed_qname_with_keyword_local_names— 23 other keywords as local namestest_prefixed_qname_with_keyword_prefix— keyword as the prefix partEnd-to-end (
xee-xpath/tests/xpath.rs):test_keyword_element_name_unprefixed— confirms//childworks without namespace (not affected)test_keyword_qname_{child,parent,self,descendant,ancestor,or,and}— full XPath evaluation against namespaced XML