Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 解析XPath表达式_C#_Xpath_Xpathnavigator - Fatal编程技术网

C# 解析XPath表达式

C# 解析XPath表达式,c#,xpath,xpathnavigator,C#,Xpath,Xpathnavigator,我正在尝试为XPath创建一个“AET”(抽象表达式树)(在编写WYSIWYG XSL编辑器时)。在过去的三到四个小时里,我一直用XPath BNF把头撞在墙上 我想到了另一个解决办法。我想我可以编写一个实现IXPathNavigatable的类,当调用CreateNavigator时,它会返回我自己的XPathNavigator。这个XPathNavigator在任何方法调用上都会成功,并且会跟踪这些调用-例如,我们先移动到customers节点,然后移动到customer节点。然后我可以使用

我正在尝试为XPath创建一个“AET”(抽象表达式树)(在编写WYSIWYG XSL编辑器时)。在过去的三到四个小时里,我一直用XPath BNF把头撞在墙上

我想到了另一个解决办法。我想我可以编写一个实现IXPathNavigatable的类,当调用CreateNavigator时,它会返回我自己的XPathNavigator。这个XPathNavigator在任何方法调用上都会成功,并且会跟踪这些调用-例如,我们先移动到customers节点,然后移动到customer节点。然后我可以使用这些信息(希望)创建“AET”(这样我们现在就可以在对象模型中有客户/客户)

唯一的问题是:我究竟如何通过XPathExpression运行IXPathNavigatable


我知道这太懒了。但是还有其他人完成了这项工作并编写了XPath表达式解析器吗?我还没有找到可能的解决方案,因为我无法测试它(因为我无法针对IXPathNavigable运行XPathExpression),所以我甚至不知道我的解决方案是否可行。

有一个antlr xpath语法。由于它的许可证允许,我在这里复制了整个语法,以避免将来链接腐烂

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 <tom@khubla.com>
*/


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'
  ;
语法xpath;
/*
XPath1.0语法。应符合
http://www.w3.org/TR/1999/REC-xpath-19991116. 语法
这些规则已尽可能地与政府的规则保持一致
规范,但一些调整是不可避免的。这些是
主要删除左递归(规范似乎基于
LR),并处理“*”标记的双重性质
(节点通配符和乘法运算符)。另见
规范第3.7节。这些规则更改应
语法所接受的字符串没有区别。
由扬·威廉·范·登·布罗克撰写
版本1.0
按照您的意愿处理此代码。
*/
/*
由汤姆·埃弗雷特移植到Antlr4
*/
主:expr
;
定位路径
:相对定位路径
|绝对位置路径根
;
绝对位置路径根
:“/”相对定位路径
|“//”相对定位路径
;
相对定位路径
:步骤((“/”|“/”)步骤)*
;
步骤:axisSpecifier节点测试谓词*
|缩略步骤
;
轴说明符
:AxisName':'
|  '@'?
;
节点测试:名称测试
|节点类型“(“”)”
|“处理指令”(“文字”)”
;
谓语
:“['expr']”
;
缩略步骤
:  '.'
|  '..'
;
expr:orExpr
;
primaryExpr
:可变参考
|“('expr')”
|文字的
|数
|函数调用
;
函数调用
:函数名“(”(expr(“,”expr)*)?”
;
联合交易所
:PathExprNot(“|”UnionExprNot)?
|“/”|“联合交易所”
;
pathExprNoRoot
:位置路径
|filterExpr((“/”|“/”)相对定位路径)?
;
过滤器出口
:primaryExpr谓词*
;
orExpr:andExpr('or'andExpr)*
;
andExpr:equalityExpr('and'equalityExpr))*
;
等式表达式
:relationalExpr((“=”|“!=”)relationalExpr)*
;
关系表达式
:additiveExpr((“”|“=”)additiveExpr)*
;
加法expr
:乘法expr((“+”|“-”)乘法expr)*
;
乘法expr
:unaryExprNoRoot((“*”|“div”|“mod”)乘法expr)?
|“/”(('div'|'mod')乘法expr)?
;
一元表达式
:“-”*联合交易所
;
qName:nCName(“:”nCName)?
;
函数名
:qName//与规范中的节点类型不匹配。
;
可变参考
:“$”qName
;
名称测试:'*'
|nCName':''*'
|qName
;
nCName:nCName
|AxisName
;
节点类型:“评论”
|“文本”
|“处理指令”
|“节点”
;
数字:数字('.'数字?)?
|“.”位
;
片段
数字:('0'..'9')+
;
名称:“祖先”
|‘祖先还是自我’
|“属性”
|“孩子”
|“后代”
|“后代或自我”
|“以下”
|“跟随兄弟姐妹”
|“名称空间”
|“家长”
|“先前的”
|“前兄弟姐妹”
|“自我”
;
帕塞普
:'/';
阿布帕斯
: '//';
LPAR
: '(';
RPAR
: ')';
LBRAC
:  '[';
RBRAC
:  ']';
减
:  '-';
加上
:  '+';
圆点
:  '.';
骡子
: '*';
圆点
:  '..';
在
: '@';
逗号
: ',';
管
:  '|';
较少的
:  '';
乐
:  '=';
结肠
:  ':';
科科斯群岛
:  '::';
载脂蛋白
:  '\'';
引用
:  '\"';
文字:'''~'''*''
|  '\'' ~'\''* '\''
;
空白
:(“|”\t“|”\n“|”\r')+->跳过
;
NCName:NCNameStartChar NCNameChar*
;
片段
NCNameStartChar
:'A'…'Z'
|   '_'
|“a”…“z”
|'\u00C0'..'\u00D6'
|'\u00D8'..'\u00F6'
|'\u00F8'..'\u02FF'
|'\u0370'..'\u037D'
|'\u037F'..'\u1ff'
|'\u200C'..'\u200D'
|“\u2070”…“\u218F”
|'\u2C00'..'\u2FEF'
|“\u3001”…”\uD7FF”
|'\uF900'..'\uFDCF'
|'\uFDF0'..'\uFFFD'
//不幸的是,java转义无法方便地处理此问题,
//因为它们被限制为4个十六进制数字。待办事项。
//|'\U010000'..'\u0efff'
;
片段
NCNameChar
:NCNameStartChar |'-'|'.|'0'..'9'
|“\u00B7”|“\u0300”…“\u036F”
|“\u203F”…“\u2040”
;

我已经编写了一个XPath解析器和一个IXPathNavigable的实现(我曾经是一名开发人员)。两者都不容易;我怀疑IXPathNavigable不会是你希望的便宜的赢家,因为不同方法之间的交互有很多微妙之处——我怀疑一个完整的XPath解析器会更简单(也更可靠)

要回答您的问题,请执行以下操作:

var results xpathNavigable.CreateNavigator().Evaluate("/my/xpath[expression]").
您可能需要枚举过多的结果,以便导航节点

如果总是返回true,那么关于以下XPath,您所知道的就是它查找foo的bar子元素:
foo[not(bar)]/other/elements

如果您总是返回固定数量的节点,那么您永远不会知道XPath的大部分内容
a[100]/b/c/

本质上,这