2012-10-01 19 views
7

Il mio modello di dati è la seguente:ottenere la maggior parte della data recente record XML

<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> 

Ho provato con la risposta data qui: XSLT: Getting the latest date ma si mangia darmi alcun valore.

Sto cercando di far passare il giocatore più giovane a una funzione esterna.

sto facendo questo in BizTalk, quindi devo attenersi a XSLT1

Il mio lavoro finora è come segue:

<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> 

Questo fa parte di un grande modello - non posso davvero cambiare questo, ma il valore di ClubRoot è "<xsl:variable name="ClubRoot" select="/*[1]"/>" assicurare riesco a leggere i suoi nodi figlio.

sto ottenendo sempre

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

come i miei valori di debug ... quindi non sono raccogliendo il valore mi aspetto

Qualcuno può evidenziare dove ho sbagliato?

Dai dati di cui sopra, mi aspetto il valore di 14-01-1993 nella mia variabile youngestPlayer. Ma è vuoto.

risposta

6

Il problema è che XSLT1.0 in realtà non ha il concetto di date, quindi si sta effettivamente ordinando gli elementi DateOfBirth come se fossero solo normali stringhe. Se si può essere sicuri le date arrivano sempre nel formato GG-MM-AAAA si potrebbe usare la manipolazione di stringhe per ordinare entro l'anno, mese e giorno

<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"/> 

Quindi, dato il seguente 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> 

Quando viene applicato al tuo XML, il seguente è uscita

14-01-1993 
+2

utilizzando la funzione translate(), è possibile ridurre il numero di xsl: sort istruzioni da 3 a 1, E semplificare 'xsl: sort/@ select expression'. –

1

il motivo per cui la data di smistamento nel vostro riferimento collegato 'lavorato' era perché era in formato yyyy-MM-dd, al contrario di y il nostro formato dd-MM-yyyy.

Un'alternativa alla proposta di Tim C/Sean consiste nell'utilizzare le funzioni di script C# (poiché si utilizza BizTalk) per ripristinare la data su un ordinabile come per il collegamento, ma si noti che è improbabile che sia performante come nativo funzioni xslt. Si noti inoltre che potrebbe essere necessario utilizzare msxsl:node-set sulle variabili per dire al parser di BizTalk che si tratta di un frammento.

<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> 

Ho preso un hack in funzione ed indovinato che il limite è 21. I minorenni rendimenti superiori

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