online herramienta expressions ejemplos consultas xml xslt xpath

herramienta - XPath 1.0 más cercano precedente y/o nodo ancestro con un atributo en un árbol XML



xpath wildcard (2)

Aquí hay tres árboles XML

(1)

<?xml version="1.0" encoding="UTF-8"?> <content> <section id="1"> <section id="2"/> <section id="3"/> <section id="9"/> </section> <section id="4"> <section id="5"> <section> <bookmark/> <!-- here''s the bookmark--> <section id="6"> <section id="7"> <section id="8"/> </section> </section> </section> </section> </section> </content>

(2)

<?xml version="1.0" encoding="UTF-8"?> <content> <section id="1"/> <section id="2"> <section id="9"> <section id="10"> <section id="11"/> </section> </section> <section> <section id="4"> <section id="5"/> </section> </section> <section/> <bookmark/> <!-- here''s the bookmark--> <section id="6"> <section id="7"> <section id="8"/> </section> </section> </section> </content>

El resultado deseado es en ambos casos el id 5 .

Con XSLT 1.0 y XPath 1.0 puedo obtener el antepasado de (1)

<xsl:value-of select="//bookmark/ancestor::*[@id][1]/@id"/>

o el nodo precedente de (2)

<xsl:value-of select="//bookmark/preceding::*[@id][1]/@id"/>

¿Cómo obtengo el antepasado o nodo anterior más cercano con un ID de mi marcador?
Necesito un solo xsl: value-of que coincida con ambos casos. Gracias.

EDITAR:

La solución también debe cubrir esta estructura. La identificación deseada sigue siendo 5 .

(3)

<?xml version="1.0" encoding="UTF-8"?> <content> <section id="1"> <section id="2"/> <section id="3"/> <section id="9"/> </section> <section id="4"> <section> <section id="10"/> <section id="5"/> <section> <bookmark/> <!-- here''s the bookmark--> <section id="6"> <section id="7"> <section id="8"/> </section> </section> </section> </section> </section> </content>


Intenta con:

<xsl:value-of select="//bookmark/ancestor::*[1]/descendant-or-self::*[last()-1]/@id"/>

Devuelve 5 para ambos documentos XML.

EDITAR:

En tales condiciones puedes usar xsl:choose simple xsl:choose :

<xsl:variable name="lastSibling" select="//bookmark/preceding-sibling::*[1]"/> <xsl:choose> <xsl:when test="$lastSibling"> <xsl:value-of select="$lastSibling/descendant-or-self::*[last()]/@id"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="//bookmark/ancestor::*[@id][1]/@id"/> </xsl:otherwise> </xsl:choose>

Otra solución general:

<xsl:for-each select="//section[following::bookmark or descendant::bookmark][@id]"> <xsl:if test="position() = last()"> <xsl:value-of select="./@id"/> </xsl:if> </xsl:for-each>


Uso :

(//bookmark/ancestor::*[@id][1]/@id | //bookmark/preceding::*[@id][1]/@id ) [last()]

Verificación : utilizando XSLT como host de XPath, la siguiente transformación:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output omit-xml-declaration="yes" indent="yes"/> <xsl:template match="/"> <xsl:value-of select= "(//bookmark/ancestor::*[@id][1]/@id | //bookmark/preceding::*[@id][1]/@id ) [last()]"/> </xsl:template> </xsl:stylesheet>

cuando se aplica en cualquiera de los tres documentos XML proporcionados, produce el resultado deseado y correcto :

5

Recomiendo encarecidamente usar el Visualizador de XPath para jugar / aprender XPath .