2009-02-05 16 views
6

मैं XPath के लिए 'एईटी' (सार अभिव्यक्ति वृक्ष) बनाने की कोशिश कर रहा हूं (जैसा कि मैं एक WYSIWYG XSL संपादक लिख रहा हूं)। मैं पिछले तीन से चार घंटों के लिए XPath BNF के साथ दीवार के खिलाफ अपना सिर मार रहा हूं।पार्स XPath अभिव्यक्ति

मैंने एक और समाधान के बारे में सोचा है। मैंने सोचा कि मैं एक कक्षा लिख ​​सकता हूं जो IXPathNavigable लागू करता है, जो CreateNavigator कहलाता है जब मैं अपने स्वयं के XPathNavigator देता है। यह XPathNavigator हमेशा किसी भी विधि कॉल पर सफल होगा, और उन कॉलों का ट्रैक रखेगा - उदा। हम ग्राहकों नोड और फिर ग्राहक नोड में चले गए। मैं फिर 'एईटी' बनाने के लिए इस जानकारी (उम्मीदपूर्वक) का उपयोग कर सकता था (इसलिए हमारे पास अब ऑब्जेक्ट मॉडल में ग्राहक/ग्राहक होंगे)।

केवल सवाल यह है कि कैसे पृथ्वी पर मैं एक XPathExpression के माध्यम से एक IXPathNavigable चला सकता हूं?

मुझे पता है कि यह अत्यधिक आलसी है। लेकिन क्या कोई और प्रयास के माध्यम से चला गया है और एक XPath अभिव्यक्ति पार्सर लिखा है? मैंने अभी तक अपना संभावित समाधान नहीं किया है, क्योंकि मैं इसका परीक्षण नहीं कर सकता (क्योंकि मैं XPXExpression को IXPathNavigable के विरुद्ध नहीं चला सकता), इसलिए मुझे यह भी नहीं पता कि मेरा समाधान भी काम करेगा या नहीं।

+0

IXPathNavigable से शुरू होने वाला आपका टेक्स्ट बहुत भ्रमित है। क्या आप सवाल संपादित कर सकते हैं और बेहतर व्याख्या कर सकते हैं? –

उत्तर

2

एक एंटरल 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' 
    ; 
+1

लिंक मर चुका है, :( –

+0

@JimCounts मुझे यकीन है कि आप 4 साल बाद इसकी तलाश नहीं कर रहे हैं, लेकिन मैंने अभी एक कामकाजी लिंक के साथ जवाब अपडेट किया है। –

+0

@jwbroek यहां आपका कोड है :) – RobAu

2

मैं दोनों में लिखा है एक XPath पार्सर और IXPathNavigable के एक कार्यान्वयन (मैं XMLPrime के लिए एक डेवलपर हुआ करता था)। न तो आसान है; और मुझे संदेह है कि IXPathNavigable आपको सस्ती जीत नहीं होने वाला है, क्योंकि विभिन्न तरीकों के बीच बातचीत में बहुत अधिक सूक्ष्मता है - मुझे संदेह है कि एक पूर्ण उड़ा XPath पार्सर सरल (और अधिक विश्वसनीय) होगा।

हालांकि आपके प्रश्न का उत्तर करने के लिए:

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

आप शायद परिणामों पर की गणना करने में पैदा करने के लिए नोड नेविगेट करने की आवश्यकता होगी।

आप हमेशा सच लौटे तो सब आप निम्नलिखित XPath के बारे में पता होता है कि यह foo की बार बच्चों के लिए लग रहा है यह है: foo[not(bar)]/other/elements

आप हमेशा नोड्स की एक निश्चित संख्या लौट हैं तो आप के बारे में कभी पता नहीं होता इस XPath a[100]/b/c/

अनिवार्य रूप से, यह काम नहीं करेगा।