2009-03-14 7 views
6

J'ai un XML comme celui-ciXSLT: Fusion scénario en double

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File1"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="123456"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

Je veux que mon XML de sortie pour être comme ce

<ContractInfo ContractNo="12345"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File1"/> 
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

<ContractInfo ContractNo="123456"> 
       <Details LastName="Goodchild">       
         <Filedata FileName="File2"/> 
       </Details> 
</ContractInfo> 

Ici, le 'fileData' se rapportant à l'appariement des besoins "contractNo" à combiner en sortie. Cette transformation peut-elle être réalisée avec XSLT?

Merci d'avance.

Srini

+0

version de XSLT et la plate-forme peut être utile – AnthonyWJones

Répondre

7

La XSLT suivante 1,0 transformation produit le résultat droite:

<xsl:stylesheet version="1.0" 
       xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="contract" match="ContractInfo" use="@ContractNo" /> 
    <xsl:key name="filedata" match="Filedata" use="../../@ContractNo" /> 

    <xsl:template match="ContractInfo"> 
    <xsl:if test="generate-id() = 
        generate-id(key('contract', @ContractNo)[1])"> 
     <xsl:copy> 
     <xsl:apply-templates select="key('contract', @ContractNo)/Details | @*" /> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    <xsl:template match="Details"> 
    <xsl:if test="generate-id(..) = 
        generate-id(key('contract', ../@ContractNo)[1])"> 
     <xsl:copy> 
     <xsl:apply-templates select="key('filedata', ../@ContractNo) | @*" /> 
     </xsl:copy> 
    </xsl:if> 
    </xsl:template> 

    <!-- copy everything else (root node, Filedata nodes and @attributes) --> 
    <xsl:template match="* | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="* | @*" /> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Notez l'utilisation de <xsl:key> conjointement avec generate-id() pour identifier le premier noeud d'un ensemble de noeuds correspondant, le regroupement efficace noeuds égal ensemble.

Vous pouvez forcer un résultat ordonné en utilisant <xsl:sort> dans le <xsl:apply-templates>. Je n'ai pas inclus cela dans un souci de clarté.

Ma sortie de test est:

<root> 
    <ContractInfo ContractNo="12345"> 
    <Details LastName="Goodchild"> 
     <Filedata FileName="File1"></Filedata> 
     <Filedata FileName="File2"></Filedata> 
    </Details> 
    </ContractInfo> 
    <ContractInfo ContractNo="123456"> 
    <Details LastName="Goodchild"> 
     <Filedata FileName="File2"></Filedata> 
    </Details> 
    </ContractInfo> 
</root> 
+0

Il est relativement facile d'étendre la transformation à exclure en double nœuds ainsi. Comme cela ne faisait pas partie de l'exigence initiale, je l'ai laissé comme un exercice pour le lecteur. ;-) Indice: Un supplémentaire et un autre est requis. – Tomalak

+0

Salut, des trucs géniaux ... y a-t-il un lien pour étudier ces concepts en détail? Pouvez-vous suggérer un qui couvre ces transformations à partir des bases? –

+0

Il existe de nombreux sites Web et didacticiels relatifs à XSLT/XPath sur Internet. Juste google les parties que vous ne comprenez pas. En fonction de votre niveau actuel de connaissances XSLT, la solution peut prendre un certain temps pour devenir transparente. ;-) – Tomalak