XSLT: seleccione distintos pero ligeramente diferentes a otros ejemplos
Pregunta
Tengo el siguiente XML:
<a>
<b>
<d>D1 content (can include child nodes)</d>
</b>
<b>
<c>C1 content (can include child nodes)</c>
</b>
<b>
<e>E1 content (can include child nodes)</e>
</b>
<b>
<c>C2 content (can include child nodes)</c>
</b>
</a>
Usando XSLT 1.0, necesito producir a partir de esto simplemente: " cde " ;; es decir, una lista distinta de los nombres de los hijos inmediatos de / a / b / ordenados por el nombre del nodo. Cada b tiene exactamente un hijo de nombre arbitrario.
Puedo producir " ccde " ;:
<xsl:for-each select="/a/b/*">
<xsl:sort select="name(.)"/>
<xsl:value-of select="name(.)" />
</xsl:for-each>
He intentado usar la comparación habitual de hermanos anteriores :: pero como cada b solo tiene un hijo, el hermano anterior siempre es nada.
Solución
Primero agregue este elemento clave a la parte superior de su XSL: -
<xsl:key name="tagNames" match="/a/b/*" use="name()" />
Ahora tu para cada bucle puede verse así:
<xsl:template match="/*">
<xsl:for-each select="/a/b/*[count(. | key('tagNames', name())[1]) = 1]">
<xsl:sort select="name()" />
<xsl:value-of select="name()" />
</xsl:for-each>
</xsl:template>
Otros consejos
Puedes usar el método Muenchian:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="groupIndex" match="*" use="name()" />
<xsl:template match="/">
<xsl:apply-templates select="a/b"/>
</xsl:template>
<xsl:template match="b">
<xsl:apply-templates select="*[1][generate-id(.) = generate-id(key('groupIndex', name())[1])]" mode="group" />
</xsl:template>
<xsl:template match="*" mode="group">
<xsl:value-of select="name()"/>
</xsl:template>
</xsl:stylesheet>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow