Tengo un problema muy particular con respecto a la clasificación con XSL 1.0 (y solo 1.0 - Estoy usando .Net Parser).Ordenar por ID y luego por marca de tiempo dentro del mismo nodo
Aquí es mi xml:
<Root>
....
<PatientsPN>
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165902</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>M</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170000</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>FannyMOI</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
</PatientsPN>
...
</Root>
quisiera ordenar mi primera PatientsNP por ID y luego tomar la mayor marca de tiempo de cada ID. Mi salida:
<Root>
<PatientsPN>
<Patient>
<ID>1</ID>
<TimeStamp>20111208165819</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>2</ID>
<TimeStamp>20111208170050</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Cmoi2</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>3</ID>
<TimeStamp>20111208165829</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Jesuis3</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
<Patient>
<ID>4</ID>
<TimeStamp>20111208165910</TimeStamp>
<NomPatient>Dudule</NomPatient>
<PrenomPatient>Fanny4</PrenomPatient>
<Sexe>F</Sexe>
</Patient>
</PatientsPN>
</Root>
En primer lugar, trató de ordenar mi lista por ID y luego analizar a través de cada nodo y utilizar XPath para extraer la marca de tiempo mayor, pero que no funcionó. Siguió repitiendo los otros nodos.
También probé el método de clasificación Muench pero no pude hacerlo funcionar correctamente con algo más genérico.
Mi XSL es:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="mark">PN</xsl:param>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="/Root/*">
<xsl:for-each select=".">
<xsl:choose>
<xsl:when test="substring(name(), (string-length(name()) - string-length($mark)) + 1) = $mark">
<!-- Search for an ID tag -->
<xsl:copy>
<xsl:if test="node()/ID">
<xsl:for-each select="node()">
<xsl:sort select="ID" order="ascending" />
<!-- So far everything I've done here failed -->
<xsl:for-each select=".[ID = '1']">
<xsl:copy>
<xsl:copy-of select="node()[not(number(TimeStamp) < (preceding-sibling::node()/TimeStamp | following-sibling::node()/TimeStamp))]"/>
</xsl:copy>
</xsl:for-each>
<!-- This is just an example, I don't want to have ID = 1 and ID = 2 -->
</xsl:for-each>
</xsl:if>
<xsl:if test="not(node()/ID)">
<xsl:copy-of select="node()[not(number(TimeStamp) < (preceding-sibling::node()/TimeStamp | following-sibling::node()/TimeStamp))]"/>
</xsl:if>
</xsl:copy>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
espero sido claro. ¡Gracias de antemano por toda la ayuda que me brindaron!
EDIT:
estoy realmente lo siento gente que debería haber mencionado que quería que sea lo más genérico posible. En mi ejemplo, estoy hablando de PatientsPN, pero lo que estoy tratando de hacer realmente es que coincida con todos los nodos de padres que terminan en PN (de ahí el final, con la versión de imitación del XSL 1.0).
Eres realmente increíble de todos modos, no podía esperar que vinieran más de ti. Gracias !
SOLUCIÓN Después de la remodelación de la solución dada por Dimitre, me ocurrió con esta XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kPatById" match="*['PN' = substring(name(), string-length(name()) -1)]/*"
use="concat(generate-id(..), '|', ID)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*['PN' = substring(name(), string-length(name()) -1)]">
<xsl:copy>
<xsl:apply-templates select="node()">
<xsl:sort select="ID" data-type="number"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="*['PN' = substring(name(), string-length(name()) -1)]/node()[TimeStamp < key('kPatById', concat(generate-id(..), '|', ID))/TimeStamp]"/>
</xsl:stylesheet>
Se hace el trabajo maravillosamente y me permite tener múltiples nodos padres que van a ser tratados y ordenado
Eso es realmente impresionante, gracias! Pero lamento que no haya explicado completamente mi problema muy bien. Realmente no puedo tener una clave xsl que coincida con un nodo predefinido porque no podré conocer mis nodos de nombre. – bosam
@bosam: actualicé ambas soluciones para implementar sus nuevos requisitos. Por favor, no vayas con los nuevos requisitos. Simplemente acepte (haga clic en la marca de verificación junto a la respuesta) la mejor respuesta a esta buena pregunta, luego haga una nueva pregunta. Me gusta su pregunta, +1. –
Actualicé su código (vea la publicación principal) y funciona de maravilla. Muchas gracias y gracias a todos por su ayuda. Me salvó a lo grande. Mensaje marcado como resuelto por esta solución. – bosam