c# - read - Expresiones Parse XPath
xpath with namespace c# (2)
Estoy intentando crear un ''AET'' (árbol de expresiones abstractas) para XPath (ya que estoy escribiendo un editor WYSIWYG XSL). He estado golpeando mi cabeza contra la pared con el XPath BNF durante las últimas tres o cuatro horas.
He pensado en otra solución. Pensé que podría escribir una clase que implementa IXPathNavigable, que devuelve un XPathNavigator propio cuando se llama a CreateNavigator. Este XPathNavigator siempre tendría éxito en cualquier llamada a un método, y haría un seguimiento de esas llamadas, por ejemplo, nos movimos al nodo de clientes y luego al nodo de clientes. Podría usar esta información (con suerte) para crear el ''AET'' (para que ahora tuviéramos clientes / clientes en un modelo de objetos).
La única pregunta es: ¿cómo demonios puedo ejecutar un IXPathNavigable a través de XPathExpression?
Sé que esto es excesivamente perezoso. Pero, ¿alguien más ha realizado el esfuerzo y ha escrito un analizador de expresiones XPath? Todavía no he considerado mi posible solución, porque no puedo probarla (porque no puedo ejecutar XPathExpression en un IXPathNavigable), así que ni siquiera sé si mi solución funcionará.
Los dos escribí un analizador XPath y una implementación de IXPathNavigable (solía ser un desarrollador de XMLPrime ). Ninguno de los dos es fácil; y sospecho que IXPathNavigable no va a ser la ganancia barata que esperas, ya que hay mucha sutileza en las interacciones entre diferentes métodos. Sospecho que un analizador XPath completo será más simple (y más confiable).
Para responder a tu pregunta:
var results xpathNavigable.CreateNavigator().Evaluate("/my/xpath[expression]").
Probablemente necesite enumerar los resultados para hacer que el nodo sea navegado.
Si siempre regresó cierto, todo lo que sabría sobre el siguiente XPath es que busca barras de elementos de foo: foo[not(bar)]/other/elements
Si siempre devuelve un número fijo de nodos, nunca sabrá sobre la mayor parte de este XPath a[100]/b/c/
Esencialmente, esto no funcionará.
Aquí hay una gramática antlr xpath. Dado que su licencia lo permite, copié toda la gramática aquí para evitar la rotura del enlace en el futuro.
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''
;