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 .