2012-11-04 6 views
0

Je voudrais transférer un fichier XML à un autre en utilisant PHP via xslt. Sur la sortie j'ai besoin de quelques ajustements, mais je ne sais pas comment ajuster ma feuille de style xsl.XML vers XML en utilisant XSLT php

Merci pour votre aide

ajustements nécessaires sur la sortie:

  • ajouter comptage dynamique à l'élément de catégorie comme <category1> <category2> ...
  • ajouter tout le contenu de l'élément CALIBRE DU PRODUIT/COULEURS/COULEUR/AVAILABLE_SIZE à <$color> élément comme <green>S:M:L:XL</green> <orange>L:M</orange>
  • ajouter dynamique comptant à l'image élément comme <image1> <image2>

la source xml:

<?xml version="1.0" encoding="utf-8"?> 
<PRODUCTS> 
<PRODUCT> 
    <CODE>19</CODE> 
    <NAME>daisy</NAME> 
    <MANUFACTURER>79</MANUFACTURER> 
    <DESCRIPTION>t-shirt</DESCRIPTION> 
    <SIZES></SIZES> 
    <PRICE>33.33</PRICE> 
    <PRICE_AKCIA>24.17</PRICE_AKCIA> 
    <CATEGORY_ID>42</CATEGORY_ID> 
    <CATEGORIES> 
    <CATEGORY>clothes</CATEGORY> 
    <CATEGORY>t-shirt</CATEGORY> 
    <CATEGORY>latest</CATEGORY> 
    </CATEGORIES> 
    <COLORS> 
    <COLOR> 
    <NAME>green</NAME> 
    <IMAGE>http://www.xyz.com/userfiles/daisy_green.png</IMAGE> 
    <AVAILABLE_SIZES> 
    <SIZE>S</SIZE> 
    <SIZE>M</SIZE> 
    </AVAILABLE_SIZES> 
    <SIZES> 
    <SIZE>S</SIZE> 
    <SIZE>M</SIZE> 
    <SIZE>L</SIZE> 
    <SIZE>XL</SIZE> 
    </SIZES> 
    </COLOR> 
    <COLOR> 
    <NAME>orange</NAME> 
    <IMAGE>http://www.xyz.com/userfiles/daisy_orange.png</IMAGE> 
    <AVAILABLE_SIZES> 
    <SIZE>L</SIZE> 
    <SIZE>M</SIZE> 
    </AVAILABLE_SIZES> 
    <SIZES> 
    <SIZE>S</SIZE> 
    <SIZE>M</SIZE> 
    <SIZE>L</SIZE> 
    <SIZE>XL</SIZE> 
    </SIZES> 
    </COLOR> 
    </COLORS> 
</PRODUCT> 
</PRODUCTS> 

xsl: stylesheet:

<?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" version="1.0" encoding="UTF-8" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:element name="products"> 
     <xsl:apply-templates select="PRODUCTS/PRODUCT"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="PRODUCTS/PRODUCT"> 
    <xsl:element name="product"> 
     <xsl:element name="id"> 
      <xsl:value-of select="CODE"/> 
     </xsl:element> 
     <xsl:element name="name"> 
      <xsl:value-of select="NAME"/> 
     </xsl:element> 
     <xsl:element name="model"> 
      <xsl:value-of select="CODE"/> 
     </xsl:element> 
     <xsl:element name="manufacturer"> 
      <xsl:value-of select="MANUFACTURER"/> 
     </xsl:element> 
     <xsl:element name="category_id"> 
      <xsl:value-of select="CATEGORY_ID"/> 
     </xsl:element> 
     <xsl:apply-templates select="CATEGORIES"/> 
     <xsl:element name="description"> 
      <xsl:value-of select="DESCRIPTION"/> 
     </xsl:element> 
     <xsl:element name="price"> 
      <xsl:value-of select="PRICE"/> 
     </xsl:element> 
     <xsl:element name="special"> 
      <xsl:value-of select="PRICE_AKCIA"/> 
     </xsl:element> 
     <xsl:apply-templates select="COLORS/COLOR"/> 
     <xsl:apply-templates select="COLORS"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="CATEGORIES"> 
    <xsl:for-each select="CATEGORY">  
     <xsl:element name="category"> 
     <xsl:value-of select="."/> 
     </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="COLORS"> 
    <xsl:for-each select="COLOR/NAME">  
     <xsl:variable name="color" select="." /> 
     <xsl:element name="{$color}"> 
     <xsl:apply-templates select="COLOR/AVAILABLE_SIZES"/> 
     </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="COLORS/COLOR"> 
    <xsl:for-each select="IMAGE">  
     <xsl:element name="image"> 
     <xsl:value-of select="."/> 
     </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

<xsl:template match="COLOR/AVAILABLE_SIZES"> 
    <xsl:for-each select="SIZE">  
     <xsl:value-of select="."/>: 
    </xsl:for-each> 
</xsl:template> 

</xsl:stylesheet> 

Résultat:

<?xml version="1.0" encoding="UTF-8"?> 
<products> 
    <product> 
    <id>19</id> 
    <name>daisy</name> 
    <model>19</model> 
    <manufacturer>79</manufacturer> 
    <category_id>42</category_id> 
    <category>clothes</category> 
    <category>t-shirt</category> 
    <category>latest</category> 
    <description>t-shirt</description> 
    <price>33.33</price> 
    <special>24.17</special> 
    <image>http://www.xyz.com/userfiles/daisy_green.png</image> 
    <image>http://www.xyz.com/userfiles/daisy_orange.png</image> 
    <green/> 
    <orange/> 
    </product> 
</products> 
+0

Bonjour! Pourriez-vous également ajouter votre résultat attendu, car cela rendrait encore plus clair ce dont vous avez besoin? Merci! –

Répondre

0

Si vous voulez avoir des éléments nommés de façon dynamique, vous pouvez utiliser la valeur d'attribut Modèles pour spécifier le nom de l'élément.

Donc, si vous vouliez category1, category2, etc, au lieu de simplement catégorie vous faire

<xsl:element name="category{position()}"> 

Les accolades indiquent ceci est une expression à evalulated.

Cependant, si vous deviez le faire directement avec votre code pour les images, vous verriez qu'ils seraient tous par suffixé 1.

<xsl:template match="COLORS/COLOR"> 
    <xsl:for-each select="IMAGE">  
     <xsl:element name="image{position()}"> 
     <xsl:value-of select="."/> 
     </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

Ceci est parce que vous obtenez la position de la IMAGE élément dans l'élément COULEUR. Vraiment, vous voulez la position de l'élément parent COULEUR. Au lieu de cela, il pourrait être préférable d'associer l'élément COULEURS ici, vous pourrez obtenir la position du l'élément COULEUR.

<xsl:template match="COLORS"> 
    <xsl:for-each select="COLOR">  
     <xsl:element name="image{position()}"> 
     <xsl:value-of select="IMAGE"/> 
     </xsl:element> 
    </xsl:for-each> 
</xsl:template> 

Bien sûr, cela signifie que vous vous retrouvez avec deux modèles correspondant COULEURS de sorte que vous voudrez probablement les combiner. Cependant, il y a un problème avec l'autre modèle. Vous itérez sur COULEUR/NOM, ce qui signifie que vous serez positionné sur un élément NAME dans la boucle. Par conséquent, lorsque vous essayez de sélectionner COLOR/AVAILABLE_SIZES, il les recherche sous l'élément actuel, où ils n'existent pas.Vous devriez probablement faire ceci

<xsl:template match="COLORS"> 
    <xsl:for-each select="COLOR">  
     <xsl:variable name="color" select="NAME" /> 
     <xsl:element name="{$color}"> 
     <xsl:apply-templates select="AVAILABLE_SIZES"/> 
     </xsl:element> 
    </xsl:for-each> 

    <!-- Code to do images from above --> 
</xsl:template> 

Un couple d'autres choses à noter. Vous n'avez vraiment besoin d'utiliser xsl: élément si vous voulez des noms d'éléments dynamiques (comme montré ci-dessus), sinon vous n'avez qu'à sortir l'élément directement.

Dans de nombreux cas, tout ce que vous faites est de convertir un nom en majuscule en minuscule. Il pourrait être plus simple d'avoir un modèle générique pour cela

<xsl:template match="*"> 
    <xsl:element name="{translate(
     local-name(), 
     'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 
     'abcdefghijklmnopqrstuvwxyz')}"> 
     <xsl:apply-templates /> 
    </xsl:element> 
</xsl:template> 

Cela réduirait le code que vous auriez besoin d'écrire. Vous n'auriez besoin que de modèles spécifiques lorsque vous souhaitez changer les noms d'éléments en quelque chose de totalement différent.

Essayez la XSLT suivante

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

    <xsl:template match="*"> 
     <xsl:element name="{translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')}"> 
     <xsl:apply-templates/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="CODE"> 
     <id> 
     <xsl:value-of select="."/> 
     </id> 
    </xsl:template> 

    <xsl:template match="PRICE_AKCIA"> 
     <special> 
     <xsl:value-of select="."/> 
     </special> 
    </xsl:template> 

    <xsl:template match="CATEGORIES"> 
     <xsl:for-each select="CATEGORY"> 
     <xsl:element name="category{position()}"> 
      <xsl:value-of select="."/> 
     </xsl:element> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="COLORS"> 
     <xsl:for-each select="COLOR"> 
     <xsl:variable name="color" select="NAME"/> 
     <xsl:element name="{$color}"> 
      <xsl:apply-templates select="AVAILABLE_SIZES"/> 
     </xsl:element> 
     </xsl:for-each> 
     <xsl:for-each select="COLOR"> 
     <xsl:element name="image{position()}"> 
      <xsl:value-of select="IMAGE"/> 
     </xsl:element> 
     </xsl:for-each> 
    </xsl:template> 

    <xsl:template match="AVAILABLE_SIZES"> 
     <xsl:for-each select="SIZE"> 
     <xsl:if test="position() > 1">:</xsl:if> 
     <xsl:value-of select="."/> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

Appliqué à votre XML exemple, ce qui suit est sortie

<products> 
    <product> 
     <id>19</id> 
     <name>daisy</name> 
     <manufacturer>79</manufacturer> 
     <description>t-shirt</description> 
     <sizes/> 
     <price>33.33</price> 
     <special>24.17</special> 
     <category_id>42</category_id> 
     <category1>clothes</category1> 
     <category2>t-shirt</category2> 
     <category3>latest</category3> 
     <green>S:M</green> 
     <orange>L:M</orange> 
     <image1>http://www.xyz.com/userfiles/daisy_green.png</image1> 
     <image2>http://www.xyz.com/userfiles/daisy_orange.png</image2> 
    </product> 
</products> 
+0

Parfait, c'est exactement ce dont j'ai besoin à la sortie, merci beaucoup – user1798073

+0

s'il vous plaît, encore une chose, si le nom de la couleur a deux mots, par exemple. bleu clair, les éléments doivent être nommés light_blue, car erreur lors de la transformation. Pls, Comment éviter cela? – user1798073

+0

Ceci est simple, en utilisant la fonction 'translate' pour remplacer un espace par un underscore. Il est probablement préférable de poser une toute nouvelle question, si vous ne pouvez pas la résoudre tout de suite, car cette question est déjà assez importante. Merci! –