2010-01-07 10 views
4

Utilisation de XML dans ce format:XML en utilisant XSLT Pivotant

<?xml version="1.0"?> 
<GetResult version="1.0"> 
<Fetch> 
    <StartTime>2004-08-01 00:00:00</StartTime> 
    <EndTime>2004-08-01 00:00:00</EndTime> 
</Fetch> 
<Items> 
    <Item> 
     <Name>Item Name Number 1</Name> 
     <Data> 
      <Datum> 
       <Timestamp>2004-07-31 16:00:00+00:00</Timestamp> 
       <Value><![CDATA[25]]></Value> 
      </Datum> 
      <Datum> 
       <Timestamp>2004-07-31 18:00:00+00:00</Timestamp> 
       <Value><![CDATA[35]]></Value> 
      </Datum> 
     </Data> 
    </Item> 
    <Item> 
     <Name>Item Number 2</Name> 
     <Data> 
      <Datum> 
       <Timestamp>2004-07-31 16:00:00+00:00</Timestamp> 
       <Value><![CDATA[45]]></Value> 
      </Datum> 
      <Datum> 
       <Timestamp>2004-07-31 17:00:00+00:00</Timestamp> 
       <Value><![CDATA[55]]></Value> 
      </Datum> 
      <Datum> 
       <Timestamp>2004-07-31 18:00:00+00:00</Timestamp> 
       <Value><![CDATA[65]]></Value> 
      </Datum> 
     </Data> 
    </Item> 
</Items> 
</GetResult> 

Je voudrais être en mesure de produire une table comme si, en utilisant XSLT:

<table> 
    <tr> 
    <th>Timestamp</th> 
    <th>Item Name Number 1</th> 
    <th>Item Number 2</th> 
    </tr> 
    <tr> 
    <td>2004-07-31 16:00:00+00:00</td> 
    <td>25</td> 
    <td>45</td> 
    </tr> 
    <tr> 
    <td>2004-07-31 17:00:00+00:00</td> 
    <td></td> 
    <td>55</td> 
    </tr> 
    <tr> 
    <td>2004-07-31 18:00:00+00:00</td> 
    <td>35</td> 
    <td>65</td> 
    </tr> 
</table> 

Cela devrait travailler indépendamment du nombre d'éléments renvoyés et du nombre de références sous chaque élément. J'ai lu d'autres réponses qui sont similaires sans aucune chance. Je suis assez nouveau pour XSLT et ça me rend fou. Une solution pour cela serait grandement appréciée.

+0

Spécifiez la version de XSLT? – AnthonyWJones

Répondre

3

Voici une méthode qui utilise la méthode plutôt effrayante de Muenchian Grouping, que vous verrez probablement mentionné si vous regardez d'autres problèmes XSLT dans StackOverflow, donc ça vaut le coup de le savoir. Dans ce cas, Muenchian Grouping sera utilisé pour faire défiler les éléments de Timestamp distict.

D'abord, vous définissez une clé pour Recherch les éléments d'horodatage

<xsl:key name="Timestamps" match="Timestamp" use="."/> 

Ainsi, si vous avez utilisé ceci pour Recherch la clé de « 2004-07-31 16: 00: 00 + 00 : 00 'il contiendrait deux timestamp, éléments, mais' 2004-07-31 17: 00: 00 + 00: 00 'n'en contiendrait qu'un.

à boucle à travers des éléments de Timestamp distincts, vous devez d'abord une boucle à travers tous les éléments Horodatage, comme si

<xsl:for-each select="//Timestamp"> 

Mais vous aurez alors besoin d'un xsl: if état pour vérifier l'élément Horodatage est la première occurence de cette valeur. Ceci est fait en utilisant la clé. Si l'élément arrive en premier dans la liste des clés, il peut être traité. Generate-id est la méthode à utiliser lorsque vous voulez tester deux éléments sont les mêmes. En le mettant tout à fait donne:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="Timestamps" match="Timestamp" use="."/> 
    <xsl:template match="/"> 
     <table> 
     <tr> 
      <th>Timestamp</th> 
      <!-- Output the Item headers --> 
      <xsl:for-each select="//Item"> 
       <th> 
        <xsl:value-of select="Name"/> 
       </th> 
      </xsl:for-each> 
     </tr> 
     <!-- Loop through all Timestamps --> 
     <xsl:for-each select="//Timestamp"> 
      <xsl:sort select="."/> 
      <!-- Only process the element if it is the first occurence of this value --> 
      <xsl:if test="generate-id(.) = generate-id(key('Timestamps',.)[1])"> 
       <xsl:variable name="Timestamp" select="."/> 
       <tr> 
        <td> 
        <xsl:value-of select="."/> 
        </td> 
        <xsl:for-each select="//Item"> 
        <td> 
         <!-- Output the relevant Value for the Item --> 
         <xsl:value-of select="Data/Datum[Timestamp=$Timestamp][1]/Value"/> 
        </td> 
        </xsl:for-each> 
       </tr> 
      </xsl:if> 
     </xsl:for-each> 
     </table> 
    </xsl:template> 
</xsl:stylesheet> 
+1

Les motifs de correspondance n'ont pas besoin de l'opérateur '//'. est assez. +1 pour l'utilisation d'une clé – Tomalak

+0

Merci pour cette info! J'ai édité ma réponse en conséquence. –

+0

+1 de moi aussi, bravo. Est-ce que [1] dans la valeur finale-de select est strictement nécessaire? – AnthonyWJones

1

Il y a peu d'étapes que vous devez faire.

  1. liste get des articles
  2. obtenir la liste des horodateurs
  3. pour chaque horodatage, vous devez imprimer la valeur pour chaque élément

Il peut sembler difficile, mais il est très simple si vous connaissez base de XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:variable name="items" select="//Item" /> 
    <xsl:variable name="timestamps" select="distinct-values(//Timestamp)" /> 

    <xsl:template match="/" > 
    <table> 
     <tr> 
     <th>Timestamp</th> 
     <xsl:for-each select="$items"> 
      <th><xsl:value-of select="Name" /></th> 
     </xsl:for-each> 
     </tr> 

     <xsl:for-each select="$timestamps"> 
     <xsl:variable name="stamp" select="."/> 
     <tr> 
      <td><xsl:value-of select="$stamp" /></td> 
      <xsl:for-each select="$items"> 
      <td><xsl:value-of select=".//Datum[ Timestamp = $stamp ]/Value" /></td> 
      </xsl:for-each> 
     </tr> 
     </xsl:for-each> 

    </table> 
    </xsl:template> 
</xsl:stylesheet> 

J'espère qu'il n'y a pas d'erreurs. S'ils sont alors désolés pour eux mais je pense que l'idée principale est claire et correcte.

Si vous avez des questions, n'hésitez pas à demander.

Questions connexes