2013-02-26 4 views
0

D'accord, je suis en train d'éditer le message original. Je suppose que j'ai essayé un peu beaucoup en remplaçant les étiquettes de nom du XML original. Quoi qu'il en soit, voici l'extrait du fichier d'origine:besoin d'aide pour transformer XML en XML en utilisant XSL

<EMPLOYEE_LIST> 
    <EMPLOYEES> 
     <EMPLOYEE> 
     <EMPID>650000</EMPID> 
     <FIRST_NAME>KEITH</FIRST_NAME> 
     <MIDDLE_NAME>HUTCHINSON</MIDDLE_NAME> 
     <LAST_NAME>ROGERS</LAST_NAME> 
     <EMP_TYPE></EMP_TYPE> 
     <EMP_REF_ID>500000</EMP_REF_ID> 
     <JOINED_ON>2001-10-06</JOINED_ON> 
     <COMMENTS>Miscellanous Comments</COMMENTS> 
     <NATIONALITY> 
      <VALUE>American</VALUE> 
     </NATIONALITY> 
     <EMP_AKA> 
      <AKA_NAME>Danny</AKA_NAME> 
     </EMP_AKA> 
     <EMP_AKA> 
      <AKA_NAME>Dan</AKANAME> 
     </EMP_AKA> 
     <EMP_AKA> 
      <AKA_NAME>Ray</AKA_NAME> 
     </EMP_AKA> 
     <EMP_ADDR> 
      <STREET> </STREET> 
      <CITY> </CITY> 
      <STATE> </STATE> 
      <ZIP> </ZIP> 
      <COUNTRY> </COUNTRY> 
     </EMPLOYEE> 
    </EMPLOYEES> 
</EMPLOYEE_LIST> 

La question que je suis confronté avec le XML ci-dessus est que je ne peux pas trouver un moyen de s'adapter multiples Alias ​​(Alias) attributs dans une propriété unique et XSL que je me sers de cette transformation est la suivante:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
     <xsl:template match="/EMPLOYEE_LIST"> 
      <employees> 
       <xsl:apply-templates select="EMPLOYEES/node()"/> 
      </employees>   
     </xsl:template> 

     <xsl:template match="EMPLOYEE"> 
     <employee> 
      <xsl:apply-templates select="*"/> 
     </employee> 
     </xsl:template> 

     xsl:template match="EMPLOYEE/EMPID"> 
     <emp_id> 
      <xsl:value-of select="."/> 
     </emp_id> 
     </xsl:template> 

      <xsl:template match="EMPLOYEE/FIRST_NAME"> 
     <f_name> 
      <xsl:value-of select="."/> 
     </f_name> 
     </xsl:template> 

     <xsl:template match="EMPLOYEE/MIDDLE_NAME"> 
      <m_name> 
       <xsl:value-of select="."/> 
      </m_name> 
     </xsl:template> 

     <xsl:template match="EMPLOYEE/LAST_NAME"> 
      <l_name> 
       <xsl:value-of select="."/> 
      </l_name> 
     </xsl:template> 
     . 
     . 
     . 
     . 
     . 
     <xsl:template match="EMPLOYEE/EMP_AKA"> 
     <aka_list> 
      <xsl:for-each select="AKA_NAME"> 
       <aka> 
        <xsl:for-each select="."> 
         <xsl:apply-templates/> 
        </xsl:for-each> 
       </aka> 
      </xsl:for-each> 
     </aka_list> 
    </xsl:template> 
</xsl:stylesheet> 

le XSL donnée ci-dessus lorsqu'il est appliqué à mon XML donne le résultat suivant:

<?xml version="1.0" encoding="UTF-8"?> 
<employees> 
     <employee> 
     <emp_id>111345</emp_id> 
     <f_name>KEITH</f_name> 
     <m_name>HUTCHINSON</m_name> 
     <l_name>ROGERS</l_name> 
     <aka_list> 
      <aka>Danny</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray</aka> 
     </aka_list> 
     </employee> 
</employees> 

ce qui est pas ce que je suis t riant pour atteindre comme j'ai besoin des données dans le format suivant:

<?xml version="1.0" encoding="UTF-8"?> 
<employees> 
     <employee> 
     <emp_id>111345</emp_id> 
     <f_name>KEITH</f_name> 
     <m_name>HUTCHINSON</m_name> 
     <l_name>ROGERS</l_name> 
     <aka_list> 
      <aka>Danny</aka> 
      <aka>Dan</aka> 
      <aka>Ray</aka> 
     </aka_list> 
     </employee> 
</employees 

Y at-il un moyen d'atteindre cet objectif? Pour aller de l'avant, il y a des éléments dans le XML qui sont en très grand nombre, par exemple AKA_NAME.

  <aka_list> 
      <aka>Danny</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Danny_2</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Dan_2</aka> 
     </aka_list> 
     <aka_list> 
      <aka>Ray_2</aka> 
     </aka_list> 

La transformation ne doit faire avancer le top 5 et le sixième devrait être tronqué comme:

  <aka_list> 
      <aka>Danny</aka> 
      <aka>Dan</aka> 
      <aka>Ray</aka> 
      <aka>Danny_2</aka> 
      <aka>Dan_2</aka> 
     </aka_list> 
+0

La sortie que vous avez publiée ne correspond pas au modèle XSLT (pas d'élément AKA_LIST dans la sortie). –

+0

' JOHN FILTER' s'ouvre avec AKA se ferme avec ALIAS, erreur de validation .. soyez sûr de votre entrée XML. –

+0

Je ne comprends pas, vous avez '' dans votre code, mais '' et '' dans votre sortie ?? Exactement celui que vous voulez ?? –

Répondre

2

MISE À JOUR: solution pour le XML complet.

J'ai essayé d'expliquer la solution en utilisant des commentaires dans le modèle XSLT.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

    <!-- Ignore text nodes by default --> 
    <xsl:template match="text()" /> 

    <!-- Transform tag name EMPLOYEES to employees --> 
    <xsl:template match="EMPLOYEES"> 
     <employees> 
      <xsl:apply-templates select="*" /> 
     </employees> 
    </xsl:template> 

    <!-- Transform tag name EMPLOYEE to employee --> 
    <xsl:template match="EMPLOYEE"> 
     <employee> 
      <xsl:apply-templates select="*" /> 
     </employee> 
    </xsl:template> 

    <!-- Transform tag name EMPID to emp_id --> 
    <xsl:template match="EMPID"> 
     <emp_id> 
      <xsl:value-of select="." /> 
     </emp_id> 
    </xsl:template> 

    <!-- Transform tag name FIRST_NAME to f_name --> 
    <xsl:template match="FIRST_NAME"> 
     <f_name> 
      <xsl:value-of select="." /> 
     </f_name> 
    </xsl:template> 

    <!-- Transform tag name MIDDLE_NAME to m_name --> 
    <xsl:template match="MIDDLE_NAME"> 
     <m_name> 
      <xsl:value-of select="." /> 
     </m_name> 
    </xsl:template> 

    <!-- Transform tag name LAST_NAME to l_name --> 
    <xsl:template match="LAST_NAME"> 
     <l_name> 
      <xsl:value-of select="." /> 
     </l_name> 
    </xsl:template> 

    <!-- When encounter the first EMP_AKA element, print itself and its following 
     siblings with the same name within an aka_list element --> 
    <xsl:template match="EMP_AKA[1]"> 
     <aka_list> 
      <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA/AKA_NAME" mode="print"/> 
     </aka_list> 
    </xsl:template> 

    <!-- Transform tag name EMP_AKA to aka --> 
    <xsl:template match="AKA_NAME" mode="print"> 
     <aka> 
      <xsl:value-of select="." /> 
     </aka> 
    </xsl:template> 

</xsl:stylesheet> 

MISE À JOUR 2: Si vous ne souhaitez pas utiliser les modes de modèle, car AKA_NAME va être adapté ailleurs et traitées de la même manière, vous pouvez remplacer les deux derniers modèles par ceux-ci :

<!-- When encounter the first EMP_AKA element, print itself and its following 
    siblings with the same name within an aka_list element --> 
<xsl:template match="EMP_AKA[1]"> 
    <aka_list> 
     <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA/AKA_NAME" /> 
    </aka_list> 
</xsl:template> 

<!-- Exclude all EMP_AKA elements (except the first one because 
    the previous template has higher precedence than this one) --> 
<xsl:template match="EMP_AKA" /> 

<!-- Transform tag name EMP_AKA to aka --> 
<xsl:template match="AKA_NAME"> 
    <aka> 
     <xsl:value-of select="." /> 
    </aka> 
</xsl:template> 

<xsl:template match="EMP_AKA" /> 

Ce code produit la même sortie que la précédente.


MISE À JOUR 3: OP a demandé sur la façon de limiter le nombre d'éléments de AKA_NAME émis. Ceci est une solution basée sur UPDATE 2. il suffit de remplacer le dernier des modèles de MISE À JOUR 2 avec

<xsl:template match="EMP_AKA[1]"> 
    <aka_list> 
     <xsl:apply-templates select="AKA_NAME|following-sibling::EMP_AKA[position() &lt; 5]/AKA_NAME" /> 
    </aka_list> 
</xsl:template> 

<!-- Transform tag name EMP_AKA to aka --> 
<xsl:template match="AKA_NAME"> 
    <aka> 
     <xsl:value-of select="." /> 
    </aka> 
</xsl:template> 

<xsl:template match="EMP_AKA" /> 

ORIGINAL RÉPONSE

L'OP a édité le message et a complètement changé le fichier XML. Ce qui suit était ma réponse précédente (n'a pas semblé juste pour l'enlever).

Si vous essayez de regrouper tous les < AKA> éléments dans un < AKA_LIST> élément (il est clair que la sortie que vous avez publié ne correspond pas à la transformation), vous pouvez alors utiliser la transformation suivante:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

    <!-- Just for demo --> 
    <xsl:template match="text()" /> 

    <!-- Match PERSON: create the list --> 
    <xsl:template match="PERSON"> 
     <AKA_LIST> 
      <xsl:apply-templates select="NAME/AKA" /> 
     </AKA_LIST> 
    </xsl:template> 

    <!-- Outputs the AKA element, changing the tag name --> 
    <xsl:template match="AKA"> 
     <aka> 
      <xsl:value-of select="." /> 
     </aka> 
    </xsl:template> 

</xsl:stylesheet> 

qui vous XML en source de transformation:

<AKA_LIST> 
    <aka>ROSE PETAL</aka> 
    <aka>JOHN FILTER</aka> 
</AKA_LIST> 
+0

belle solution Pablo, seulement en utilisant des correspondances de modèle et apply-templates. +1 – Peter

+0

'' non requis .. coz ce n'est pas une exigence pour renommer .. Aussi une meilleure pratique serait de remplacer le modèle d'identité .. –

+0

Eh bien, nous n'allons pas savoir que jusqu'à ce que l'OP clarifie dans son message ce qu'il essaie de faire. J'ai fait une supposition sur ce qu'il essaie de faire et j'ai posté la solution pour cela. Je ne pense pas que nous puissions supposer si c'est ou ce n'est pas une obligation de renommer (imaginez qu'il va utiliser XML Schema après cela pour valider le XML de sortie) –

1

Votre code XSLT embrouille en fait parce que vous avez des balises comme <AKA_LIST>. Je vais donc des échantillons XML d'entrée et de sortie: voici le code XSLT

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="PERSON"> 
    <xsl:copy> 
     <xsl:apply-templates select="NAME[1]"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="NAME"> 
    <xsl:copy> 
     <xsl:apply-templates select="/PEOPLE/PERSON/NAME/AKA"/> 
    </xsl:copy> 
    </xsl:template> 


</xsl:stylesheet> 

XML d'entrée:

<?xml version="1.0" encoding="utf-8"?> 
<PEOPLE> 
    <PERSON> 
    <NAME> 
     <REFERENCE>GOOD</REFERENCE> 
     <AKA>ROSE PETAL</AKA> 
     </NAME> 
    <NAME> 
     <REFERENCE>GOOD</REFERENCE> 
     <AKA>JOHN FILTER</AKA> 
     </NAME> 
    </PERSON> 
</PEOPLE> 

Sortie:

<?xml version="1.0" encoding="utf-8"?> 
<PEOPLE> 
    <PERSON> 
    <NAME> 
     <AKA>ROSE PETAL</AKA> 
     <AKA>JOHN FILTER</AKA> 
    </NAME> 
    </PERSON> 
</PEOPLE> 

Explication:

<xsl:template match="@*|node()"> ...... 

les copies de code ci-dessus les balises d'entrée à la sortie AS IS *, Autre template match remplacer ce ..

<xsl:template match="PERSON"> ...... 

les copies de code ci-dessus qu'UNE <NAME> TAG (premier) en sortie ..

<xsl:template match="NAME"> 
    <xsl:copy> 
     <xsl:apply-templates select="/PEOPLE/PERSON/NAME/AKA"/> 
     ...... 

le code ci-dessus copie tous<AKA>étiquettes sous<NAME>. Comme nous ne copions qu'une seule balise <NAME>, tous les balises <AKA> apparaissent sous <NAME>