xslt biztalk

xslt - Obtener la fecha más reciente en los registros xml



biztalk (2)

El problema es que XSLT1.0 realmente no tiene el concepto de fechas, por lo que está ordenando efectivamente por los elementos DateOfBirth como si fueran cadenas normales. Si puede estar seguro de que las fechas siempre vienen en el formato DD-MM-YYYY, puede usar la manipulación de cadenas para ordenar por año, mes y día.

<xsl:sort select="number(substring(DateOfBirth, 7, 4))" order="descending"/> <xsl:sort select="number(substring(DateOfBirth, 3, 2))" order="descending"/> <xsl:sort select="number(substring(DateOfBirth, 1, 2))" order="descending"/>

Entonces, dado el siguiente XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/Club"> <xsl:for-each select="PlayingStaff/Player"> <xsl:sort select="number(substring(DateOfBirth, 7, 4))" order="descending"/> <xsl:sort select="number(substring(DateOfBirth, 3, 2))" order="descending"/> <xsl:sort select="number(substring(DateOfBirth, 1, 2))" order="descending"/> <xsl:if test="position() = 1"> <xsl:value-of select="DateOfBirth"/> </xsl:if> </xsl:for-each> </xsl:template> </xsl:stylesheet>

Cuando se aplica a su XML, se muestra el siguiente

14-01-1993

Mi modelo de datos es el siguiente:

<Club> <Captain> <Name></Name> <DateOfBirth>15-01-1985</DateOfBirth> </Captain> <PlayingStaff> <Player> <DateOfBirth>14-01-1993</DateOfBirth> </Player> <Player> <DateOfBirth>07-12-1975</DateOfBirth> </Player> <Player> <DateOfBirth>11-11-1991</DateOfBirth> </Player> </PlayingStaff> </Club>

He intentado usar la respuesta que se da aquí: XSLT: Obtener la fecha más reciente, pero no me da ningún valor.

Intento que el jugador más joven pase a una función externa.

Estoy haciendo esto en Biztalk, así que tengo que seguir con XSLT1

Mi trabajo hasta ahora es el siguiente:

<xsl:variable name="youngestPlayer"> <xsl:for-each select="$ClubRoot/*[local-name()=''PlayingStaff'']/*[local-name()=''Player'']"> <xsl:sort select="./*[local-name()=''DateOfBirth'']" order="descending"/> <xsl:if test="position() = 1"> <xsl:value-of select="DateOfBirth"/> </xsl:if> </xsl:for-each> </xsl:variable> <xsl:variable name="IsYoungestPlayerUnderAgeLimit" select="externalfunctionreturningboolean"> <xsl:element name="blahhh"><xsl:value-of select="$IsYoungestPlayerUnderAgeLimit"/></xsl:element> <xsl:element name="blahhh"><xsl:value-of select="$youngestPlayer"/></xsl:element>

Esto es parte de una plantilla grande: realmente no puedo cambiar esto, pero el valor de ClubRoot es " <xsl:variable name="ClubRoot" select="/*[1]"/>" para asegurar que pueda leer su nodos secundarios.

Siempre estoy recibiendo

<blahhh>false</blahhh> <blahhh/>

como mis valores de depuración ... así que no estoy recogiendo el valor que espero

¿Alguien puede resaltar dónde me he equivocado?

De los datos anteriores, esperaría el valor de 14-01-1993 en la variable Player más reciente. Pero está en blanco.


La razón por la cual la clasificación de fecha en su referencia vinculada ''funcionó'' se debía a que estaba en formato yyyy-MM-dd , a diferencia de su formato dd-MM-yyyy .

Una alternativa a la propuesta de Tim C / Sean es usar las funciones de script C # (ya que está utilizando BizTalk) para revertir la fecha a una ordenable como su enlace, pero tenga en cuenta que es poco probable que sea tan eficaz como las funciones xslt nativas. Tenga en cuenta también que puede necesitar usar msxsl: node-set en sus variables para decirle al analizador de BizTalk que se trata de un fragmento.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:userCSharp="http://schemas.microsoft.com/BizTalk/2003/userCSharp" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="userCSharp msxsl" > <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <xsl:variable name="ClubRoot" select="/*[1]"/> <xsl:variable name="orderedPlayers"> <xsl:for-each select="msxsl:node-set($ClubRoot)/*[local-name()=''PlayingStaff'']/*[local-name()=''Player'']"> <xsl:sort select="userCSharp:makeSortableDate(string(*[local-name()=''DateOfBirth'']), ''dd-MM-yyyy'')" order="descending"/> <xsl:copy-of select="node() | @*"/> </xsl:for-each> </xsl:variable> <xsl:variable name="youngestPlayerDOB"> <xsl:value-of select="msxsl:node-set($orderedPlayers)[1]/DateOfBirth/text()" /> </xsl:variable> <xsl:element name="blahhh"> <xsl:variable name="IsYoungestPlayerUnderAgeLimit" select="userCSharp:externalfunctionreturningboolean($youngestPlayerDOB)" /> <xsl:value-of select="$IsYoungestPlayerUnderAgeLimit"/> </xsl:element> <xsl:element name="blahhh"> <xsl:value-of select="$youngestPlayerDOB"/> </xsl:element> </xsl:template> <msxsl:script language="C#" implements-prefix="userCSharp"> <![CDATA[ public System.String makeSortableDate(System.String yourDate, string format) { return (System.DateTime.ParseExact(yourDate, format, System.Globalization.CultureInfo.InvariantCulture).ToString("yyyy-MM-dd")); } public bool externalfunctionreturningboolean(System.String dobString) { System.DateTime someDate; if (System.DateTime.TryParse(dobString, out someDate)) { // NB : Doesn''t work out leap years correctly! if ((System.DateTime.Now - someDate).Days < 21 * 365.25) { return true; } } return false; } ]]> </msxsl:script> </xsl:stylesheet>

He tomado un truco en la función y he adivinado que el límite de menores de edad es 21. Lo anterior regresa

<blahhh>true</blahhh> <blahhh>14-01-1993</blahhh>