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
conid="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;''.