regulares online expressions expresiones xpath

online - xpath value



XPath: selecciona todos los hermanos siguientes hasta que otro hermano (3)

Más simple que la respuesta aceptada:

//node[@id=''1'']/following-sibling::node[following::node[@id=''2'']]

  • Encuentra un nodo en cualquier lugar cuya ID sea ''1''
  • Ahora encuentre todos los siguientes elementos del node hermano
  • ... pero solo si esos elementos también tienen un node con id="2" algún lugar después de ellos.

Se muestra en acción con un documento de prueba más claro (y valores legales de id ):

xml = ''<root> <node id="a"/><node id="b"/> <node id="c">content</node> <node id="d"/><node id="e"/><node id="f"/> <node id="g">content</node> <node id="h"/><node id="i"/> </root>'' # A Ruby library that uses libxml2; http://nokogiri.org require ''nokogiri''; doc = Nokogiri::XML(xml) expression = "//node[@id=''c'']/following-sibling::node[following::node[@id=''g'']]" puts doc.xpath(expression) #=> <node id="d"/> #=> <node id="e"/> #=> <node id="f"/>

Aquí hay un extracto de mi xml:

<node/> <node/> <node id="1">content</node> <node/> <node/> <node/> <node id="2">content</node> <node/> <node/>

Estoy posicionado en el node[@id=''1''] . Necesito un Xpath para unir todos los elementos <node/> hasta el siguiente nodo no vacío (aquí node[@id=''2''] ).

Editar: los atributos @id son solo para explicar mi problema más claramente, pero no están en mi XML original. Necesito una solución que no use los atributos @id.

No quiero hacer coincidir los hermanos vacíos después del node[@id=''2''] , así que no puedo usar un ingenuo following-sibling::node[text()=''''] .

Cómo puedo conseguir esto ?


Podrías hacerlo de esta manera:

../node[not(text()) and preceding-sibling::node[@id][1][@id=''1'']]

donde ''1'' es la identificación del nodo actual (genera la expresión dinámicamente).

La expresión dice:

  • desde el contexto actual, ve al padre
  • seleccione esos nodos secundarios que
  • no tener texto y
  • de todos los "nodos hermanos anteriores que tienen un id", el primero debe tener una identificación de 1

Si está en XSLT, puede seleccionar uno de los siguientes ejes hermanos porque puede usar la función current() :

<!-- the for-each is merely to switch the current node --> <xsl:for-each select="node[@id=''1'']"> <xsl:copy-of select=" following-sibling::node[ not(text()) and generate-id(preceding-sibling::node[@id][1]) = generate-id(current()) ] " /> </xsl:for-each>

o más simple (y más eficiente) con una clave:

<xsl:key name="kNode" match="node[not(text())]" use="generate-id(preceding-sibling::node[@id][1])" /> <xsl:copy-of select="key(''kNode'', generate-id(node[@id=''1'']))" />


XPath 2.0 tiene los operadores ''<<'' y ''>>'' donde node1 << node2 es verdadero si el nodo1 precede al nodo2 en orden de documento. Por lo tanto, basado en eso con XPath 2.0 en una hoja de estilos XSLT 2.0 donde el nodo actual es el nodo [@id = ''1''] podría usar

following-sibling::node[not(text()) and . << current()/following-sibling::node[@od][1]]

Eso también necesita la función actual () de XSLT, así que es por eso que dije "con XPath 2.0 en una hoja de estilos XSLT 2.0". La sintaxis anterior es XPath puro, en una hoja de estilo XSLT necesitaría escapar ''<<'' como ''& lt; & lt;''.