我正在尝试为 XPath 创建一个“AET”(抽象表达式树)(因为我正在编写一个 WYSIWYG XSL 编辑器)。在过去的三到四个小时里,我一直在与 XPath BNF 碰头。
我想到了另一个解决方案。我想我可以编写一个实现 IXPathNavigable 的类,它在调用 CreateNavigator 时返回我自己的 XPathNavigator。这个 XPathNavigator 在任何方法调用上总是会成功,并且会跟踪这些调用 - 例如我们转移到客户节点,然后转移到客户节点。然后我可以使用这些信息(希望)来创建“AET”(这样我们现在就可以在对象模型中拥有客户/客户)。
唯一的问题是:如何earth我如何通过 XPathExpression 运行 IXPathNavigable?
我知道这样太懒了。但是还有其他人付出了努力并编写了 XPath 表达式解析器吗?我还没有对我可能的解决方案进行 POC,因为我无法测试它(因为我无法针对 IXPathNavigable 运行 XPathExpression),所以我什至不知道我的解决方案是否有效。
有一个antlr xpath语法here。由于其许可证允许,我在这里复制了整个语法,以避免将来链接失效。
grammar xpath;
/*
XPath 1.0 grammar. Should conform to the official spec at
http://www.w3.org/TR/1999/REC-xpath-19991116. The grammar
rules have been kept as close as possible to those in the
spec, but some adjustmewnts were unavoidable. These were
mainly removing left recursion (spec seems to be based on
LR), and to deal with the double nature of the '*' token
(node wildcard and multiplication operator). See also
section 3.7 in the spec. These rule changes should make
no difference to the strings accepted by the grammar.
Written by Jan-Willem van den Broek
Version 1.0
Do with this code as you will.
*/
/*
Ported to Antlr4 by Tom Everett <[email protected]>
*/
main : expr
;
locationPath
: relativeLocationPath
| absoluteLocationPathNoroot
;
absoluteLocationPathNoroot
: '/' relativeLocationPath
| '//' relativeLocationPath
;
relativeLocationPath
: step (('/'|'//') step)*
;
step : axisSpecifier nodeTest predicate*
| abbreviatedStep
;
axisSpecifier
: AxisName '::'
| '@'?
;
nodeTest: nameTest
| NodeType '(' ')'
| 'processing-instruction' '(' Literal ')'
;
predicate
: '[' expr ']'
;
abbreviatedStep
: '.'
| '..'
;
expr : orExpr
;
primaryExpr
: variableReference
| '(' expr ')'
| Literal
| Number
| functionCall
;
functionCall
: functionName '(' ( expr ( ',' expr )* )? ')'
;
unionExprNoRoot
: pathExprNoRoot ('|' unionExprNoRoot)?
| '/' '|' unionExprNoRoot
;
pathExprNoRoot
: locationPath
| filterExpr (('/'|'//') relativeLocationPath)?
;
filterExpr
: primaryExpr predicate*
;
orExpr : andExpr ('or' andExpr)*
;
andExpr : equalityExpr ('and' equalityExpr)*
;
equalityExpr
: relationalExpr (('='|'!=') relationalExpr)*
;
relationalExpr
: additiveExpr (('<'|'>'|'<='|'>=') additiveExpr)*
;
additiveExpr
: multiplicativeExpr (('+'|'-') multiplicativeExpr)*
;
multiplicativeExpr
: unaryExprNoRoot (('*'|'div'|'mod') multiplicativeExpr)?
| '/' (('div'|'mod') multiplicativeExpr)?
;
unaryExprNoRoot
: '-'* unionExprNoRoot
;
qName : nCName (':' nCName)?
;
functionName
: qName // Does not match nodeType, as per spec.
;
variableReference
: '$' qName
;
nameTest: '*'
| nCName ':' '*'
| qName
;
nCName : NCName
| AxisName
;
NodeType: 'comment'
| 'text'
| 'processing-instruction'
| 'node'
;
Number : Digits ('.' Digits?)?
| '.' Digits
;
fragment
Digits : ('0'..'9')+
;
AxisName: 'ancestor'
| 'ancestor-or-self'
| 'attribute'
| 'child'
| 'descendant'
| 'descendant-or-self'
| 'following'
| 'following-sibling'
| 'namespace'
| 'parent'
| 'preceding'
| 'preceding-sibling'
| 'self'
;
PATHSEP
:'/';
ABRPATH
: '//';
LPAR
: '(';
RPAR
: ')';
LBRAC
: '[';
RBRAC
: ']';
MINUS
: '-';
PLUS
: '+';
DOT
: '.';
MUL
: '*';
DOTDOT
: '..';
AT
: '@';
COMMA
: ',';
PIPE
: '|';
LESS
: '<';
MORE_
: '>';
LE
: '<=';
GE
: '>=';
COLON
: ':';
CC
: '::';
APOS
: '\'';
QUOT
: '\"';
Literal : '"' ~'"'* '"'
| '\'' ~'\''* '\''
;
Whitespace
: (' '|'\t'|'\n'|'\r')+ ->skip
;
NCName : NCNameStartChar NCNameChar*
;
fragment
NCNameStartChar
: 'A'..'Z'
| '_'
| 'a'..'z'
| '\u00C0'..'\u00D6'
| '\u00D8'..'\u00F6'
| '\u00F8'..'\u02FF'
| '\u0370'..'\u037D'
| '\u037F'..'\u1FFF'
| '\u200C'..'\u200D'
| '\u2070'..'\u218F'
| '\u2C00'..'\u2FEF'
| '\u3001'..'\uD7FF'
| '\uF900'..'\uFDCF'
| '\uFDF0'..'\uFFFD'
// Unfortunately, java escapes can't handle this conveniently,
// as they're limited to 4 hex digits. TODO.
// | '\U010000'..'\U0EFFFF'
;
fragment
NCNameChar
: NCNameStartChar | '-' | '.' | '0'..'9'
| '\u00B7' | '\u0300'..'\u036F'
| '\u203F'..'\u2040'
;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)