2009-02-05 39 views
6

Tôi đang cố gắng tạo 'AET' (Cây biểu thức trừu tượng) cho XPath (khi tôi đang viết trình soạn thảo XSL WYSIWYG). Tôi đã đánh đầu vào tường với BN BN XPath trong ba đến bốn giờ qua.Biểu thức XPath phân tích

Tôi đã nghĩ đến một giải pháp khác. Tôi nghĩ rằng tôi có thể viết một lớp thực hiện IXPathNavigable, trả về một XPathNavigator của riêng tôi khi CreateNavigator được gọi. XPathNavigator này sẽ luôn thành công trên bất kỳ cuộc gọi phương thức nào và sẽ theo dõi các cuộc gọi đó - ví dụ: chúng tôi đã chuyển sang nút khách hàng và sau đó là nút khách hàng. Sau đó tôi có thể sử dụng thông tin này (hy vọng) để tạo ra 'AET' (vì vậy chúng tôi sẽ có khách hàng/khách hàng trong một mô hình đối tượng ngay bây giờ).

Câu hỏi duy nhất là: cách trên earth để tôi chạy IXPathNavigable thông qua XPathExpression?

Tôi biết điều này quá lười biếng. Nhưng có ai khác đã trải qua nỗ lực này và viết một trình phân tích cú pháp biểu thức XPath không? Tôi chưa POC giải pháp có thể của tôi, bởi vì tôi không thể kiểm tra nó (bởi vì tôi không thể chạy XPathExpression chống lại một IXPathNavigable), vì vậy tôi thậm chí không biết nếu giải pháp của tôi thậm chí sẽ làm việc.

+0

Văn bản của bạn bắt đầu từ IXPathNavigable rất khó hiểu. Bạn có thể chỉnh sửa câu hỏi và giải thích rõ hơn không? –

Trả lời

2

Có ngữ pháp xpath antlr here. Kể từ khi giấy phép của nó được cấp phép, tôi đã sao chép toàn bộ ngữ pháp ở đây để tránh sự liên kết bị thối trong tương lai.

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' 
    ; 
+1

Liên kết đã chết,: ( –

+0

@JimCounts Tôi chắc chắn bạn không tìm kiếm điều này sau 4 năm, nhưng tôi vừa cập nhật câu trả lời bằng liên kết hoạt động. –

+0

@jwbroek đây là mã của bạn :) – RobAu

2

Tôi đã viết cả một trình phân tích cú pháp XPath và triển khai IXPathNavigable (Tôi từng là nhà phát triển cho XMLPrime). Không dễ dàng; và tôi nghi ngờ rằng IXPathNavigable sẽ không phải là chiến thắng giá rẻ bạn hy vọng, vì có khá nhiều sự tinh tế trong tương tác giữa các phương pháp khác nhau - tôi nghi ngờ một trình phân tích cú pháp XPath đầy đủ sẽ đơn giản hơn (và đáng tin cậy hơn).

Để trả lời câu hỏi của bạn mặc dù:

var results xpathNavigable.CreateNavigator().Evaluate("/my/xpath[expression]"). 

Bạn có lẽ cần phải liệt kê trên kết quả gây ra các nút để điều hướng.

Nếu bạn luôn luôn trở thành sự thật thì tất cả các bạn muốn biết về XPath sau là nó trông cho trẻ em thanh của foo: foo[not(bar)]/other/elements

Nếu bạn luôn luôn trả về một số cố định của các nút sau đó bạn không bao giờ biết về hầu hết XPath này a[100]/b/c/

Về cơ bản, điều này sẽ không hoạt động.

Các vấn đề liên quan