2010-08-08 5 views
7

Je voudrais utiliser un fichier xmlComment obtenir le chemin d'image pour <img src="?"> tag de fichier XML

<pics> 
<pic no="1">c:\pic1.jpg</pic> 
<pic no="2">c:\pic2.jpg</pic> 
<pic no="3">c:\pic3.jpg</pic> 
<pic no="4">c:\pic4.jpg</pic> 
<pic no="5">c:\pic5.jpg</pic> 
.... 
</pics> 

dans une table html:

<table cellspacing="2" cellpadding="2" border="0">    
    <tr> 
    <td><img src="" width="150" height="120" /></td> 
    <td><img src="" width="150" height="120" /></td> 
    <td><img src="" width="150" height="120" /></td> 

    </tr> 
    <tr> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    </tr> 
    <tr> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    <td><img src="from xml" width="150" height="120" /></td> 
    </tr>      
</table> 

Quelle est la meilleure façon de le faire?

+0

Bonne question (+1). Voir ma réponse pour une solution complète qui est dans l'esprit de XSLT et pour une explication de tous les moments significatifs de la solution. :) –

Répondre

3

XML:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<?xml-stylesheet type="text/xsl" href="web_page.xsl"?> 
<pics> 
    <pic> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">1</no> 
    </td> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">2</no> 
    </td> 
    <td> 
    <no src="http://farm1.static.flickr.com/160/387667598_ea86c93d81.jpg" width="150" height="120">3</no> 
    </td> 
    </pic> 
    <pic> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">4</no> 
    </td> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">5</no> 
    </td> 
    <td> 
    <no src="http://motherjones.com/files/legacy/mojoblog/funny-cats-a10.jpg" width="150" height="120">6</no> 
    </td> 
    </pic> 
</pics> 

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template match="/"> 
<html> 
<body> 
    <table> 
    <xsl:for-each select="pics/pic"> 
    <tr> 
     <xsl:for-each select="td"> 
     <td><img> 
      <xsl:attribute name="src"> 
      <xsl:value-of select="no//@src"/> 
      </xsl:attribute> 
      <xsl:attribute name="width"> 
      <xsl:value-of select="no//@width"/> 
      </xsl:attribute> 
      <xsl:attribute name="height"> 
      <xsl:value-of select="no//@height"/> 
      </xsl:attribute> 
     </img></td> 
     </xsl:for-each> 
    </tr> 
    </xsl:for-each> 
    </table> 
</body> 
</html> 
</xsl:template> 
</xsl:stylesheet> 

Essayez vous-même ici (copier-coller mon code dans la boîtes appropriées):

+0

Cela ne gère pas la partie la plus délicate (organiser les colonnes de la table), est trop verbeux ('' a le même résultat) et est buggy car vous ne pouvez pas avoir un élément d'image sans attribut alt et ne pouvez pas avoir un élément d'image en tant qu'enfant d'un élément body. –

+1

@Jon: laissez-moi répondre à vos commentaires. ** 1. ** arranger la table html est trivial, je suppose qu'il pourrait comprendre cette partie, mais pour vous j'ai mis à jour mon exemple pour faire exactement ce qu'il essaie de réaliser (tester vous-même) ** 2. exemple est beaucoup plus compliqué que le mien, surtout pour quelqu'un qui commence avec XSLT, le mien fait ce qu'il doit faire et est simple ** 3. ** Je ne vois pas comment c'est bogué, vous pouvez mettre le 'img' n'importe où, mon exemple ** fonctionne! ** Je suis confus quant à savoir pourquoi vous avez voté. Bonne journée. – JohnB

+1

Je suis d'accord avec JohnB - simple est toujours une meilleure solution à mon avis surtout si vous commencez juste à apprendre une nouvelle technologie - essayer de maîtriser le concept est assez difficile sans avoir à patauger si sténo cryptique - je dis toujours - "le garder simple stupide " – Doug

1

Utilisez XSL. Exemple here. BTW pourquoi avez-vous l'attribut no là?

+1

Bien sûr, il est même marqué comme [xslt] ... – kennytm

2

Il y a un bug dans la sortie suggéré, comme <img/> éléments doivent avoir alt attributs dans toutes les versions de HTML où ils sont présents.

De toute façon ce qui suit le fait, mais sans les attributs qui peuvent être faits à partir de CSS à la place (juste pour réduire la taille). les rajoutant si désiré est trivial:

<xsl:template match="pics"> 
    <table> 
     <xsl:apply-templates select="pic[position() mod 3 = 1]"/> 
    </table> 
</xsl:template> 
<xsl:template match="pic[position() mod 3 = 1]"> 
    <tr> 
     <td> 
      <xsl:if test="2 &gt; count(following-sibling::pic)"> 
       <xsl:attribute name="colspan"> 
        <xsl:value-of select="3 - count(following-sibling::pic)"/> 
       </xsl:attribute> 
      </xsl:if> 
      <img src="{.}" alt="" /> 
     </td> 
     <xsl:apply-templates select="following-sibling::pic[3 &gt; position()]" /> 
    </tr> 
</xsl:template> 
<xsl:template match="pic"> 
    <td><img src="{.}" alt=""/></td> 
</xsl:template> 

qui précède suppose que vous voulez que le chemin du fichier utilisé directement, en ajoutant le code pour le transformer en quelque sorte (dire en prenant la dernière partie du chemin en utilisant substring-after()) n'est pas une extension difficile, en supposant que cette transformation n'est pas compliquée elle-même.

Edit:

Moi-même et JohnB vont dans le territoire plus ici, les suffixes ci-dessus pour répondre à la question initiale.

Ajouté pour donner une réponse plus complète à la question de JohnB. Ce qui suit est le code équivalent utilisant for-each au lieu de apply-templates. En théorie, une implémentation séquentielle et basée sur une machine d'état d'un processeur XSLT devrait traiter de la même façon, bien que vous puissiez trouver des différences dans la pratique (si vous me disiez qu'ils étaient différents avec un processeur donné, je parierais un peu étant légèrement plus rapide avec le traitement séquentiel et légèrement plus lent avec le traitement de machine-état, mais je parierais seulement une très petite quantité).

Notez que nous ne pouvons pas réutiliser le modèle par défaut pour l'image. Sur le côté positif, si nous avons un autre modèle par défaut pour la photo ailleurs (si cela faisait partie d'une feuille de style beaucoup plus compliquée), nous n'avons pas besoin d'être intelligent pour les différencier, ce qui est la principale pencherait vers-chacun.

<xsl:template match="pics"> 
    <table> 
    <xsl:for-each select="pic[position() mod 3 = 1]"> 
      <tr> 
       <td> 
        <xsl:if test="2 &gt; count(following-sibling::pic)"> 
         <xsl:attribute name="colspan"> 
          <xsl:value-of select="3 - count(following-sibling::pic)"/> 
        </xsl:attribute> 
        </xsl:if> 
        <img src="{.}" alt="" /> 
       </td> 
       <xsl:for-each select="following-sibling::pic[3 &gt; position()]"> 
        <td><img src="{.}" alt=""/></td> 
       </xsl:for-each> 
      </tr> 
     </xsl:for-each> 
    </table> 
</xsl:template> 
+0

+1 très astucieux pour générer les colonnes! Je n'ai jamais rien fait de tel avec XSLT. Mais n'avez-vous pas besoin d'une boucle autour du ''? – JohnB

+0

Nous n'avons pas besoin d'une boucle, car les templates d'application dans la table prendront toutes les troisièmes images dans l'ordre et ensuite le modèle approprié sera exécuté dessus, qui à son tour traitera les deux suivants. Ou pour le regarder d'une autre manière, apply-templates est une boucle, bien que parfois une boucle sur un seul élément. Il y a très peu de choses que vous pouvez faire avec for-each que vous ne pouvez pas faire avec apply-templates, et vice-versa. La différence est normalement à propos de ce qui semble plus naturel à l'époque, ce qui dépend du style de codeur dans une certaine mesure. Je me penche sur apply-templates comme sans doute plus déclaratif, et plus propice à la réutilisation –

+0

@JohnB J'ai ajouté une implémentation pour chaque et une explication de la différence pour répondre plus complètement à cette question. –

0

Voici une solution typique qui adhère à l'esprit de XSLT (pas <xsl:for-each>), aussi courte que possible et paramétrés sur le nombre souhaité de colonnes dans la table.

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

    <xsl:param name="pNumCols" select="3"/> 

<xsl:template match="pics"> 
    <table cellspacing="2" cellpadding="2" border="0"> 
    <xsl:apply-templates select="pic[position() mod $pNumCols = 1]"/> 
    </table> 
</xsl:template> 

<xsl:template match="pic"> 
    <tr> 
    <xsl:apply-templates mode="process" select= 
    "(. | following-sibling::pic)[not(position() > $pNumCols)]"/> 
    </tr> 
</xsl:template> 

<xsl:template match="pic" mode="process"> 
    <td><img src="{.}" width="150" height="120" /></td> 
</xsl:template> 
</xsl:stylesheet> 

Lorsque cette transformation est appliquée sur le document XML suivant (basé sur le document XML fourni, mais avec plus d'images qui sont vraiment coloré et intéressant):

<pics> 
<pic no="1">http://col.stb.s-msn.com/i/D7/6A19748C9AA58B938F42099543D2E.jpg</pic> 
<pic no="2">http://col.stb.s-msn.com/i/1F/35A8478AC24EEF95933B5F0E4E394.jpg</pic> 
<pic no="3">http://col.stb.s-msn.com/i/76/3ADA01320CEC8B31D53FACC0C11E.jpg</pic> 
<pic no="4">http://col.stb.s-msn.com/i/92/51BF117987A3279571F06BEB4AE39D.jpg</pic> 
<pic no="5">http://col.stb.s-msn.com/i/9B/9A6E876BA2F7EAE82392C7E7F6C1C.jpg</pic> 
<pic no="6">http://col.stb.s-msn.com/i/50/8CC964E5503A7F61F8AD22A12024.jpg</pic> 
<pic no="7">http://col.stb.s-msn.com/i/C4/F7EF634B7084DA69AAB5AAD05C8922.jpg</pic> 
<pic no="8">http://col.stb.s-msn.com/i/FB/C8367425D67FA391A5E0F8A3E0276B.jpg</pic> 
</pics> 

le résultat recherché est produit (voir aussi dans un navigateur :)):

<table cellspacing="2" cellpadding="2" border="0"> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/D7/6A19748C9AA58B938F42099543D2E.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/1F/35A8478AC24EEF95933B5F0E4E394.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/76/3ADA01320CEC8B31D53FACC0C11E.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/92/51BF117987A3279571F06BEB4AE39D.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/9B/9A6E876BA2F7EAE82392C7E7F6C1C.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/50/8CC964E5503A7F61F8AD22A12024.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
    <tr> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/C4/F7EF634B7084DA69AAB5AAD05C8922.jpg" width="150" height="120"/> 
     </td> 
     <td> 
     <img src="http://col.stb.s-msn.com/i/FB/C8367425D67FA391A5E0F8A3E0276B.jpg" width="150" height="120"/> 
     </td> 
    </tr> 
</table> 

Prenez note:

  1. L'utilisation de l'opérateur XPath mod pour déterminer les éléments de chaque rangée.

  2. L'utilisation de modes pour traiter le même type d'élément (<pic>) de deux manières différentes.

  3. L'utilisation de AVT (attribute-value-templates) pour rendre le code plus court et plus compréhensible.

+0

Il semble très élégant ... mais je suis moins qu'un débutant - je n'ai jamais vraiment eu le temps de comprendre la magie du xslt. J'ai essayé de copier et coller votre code changez les URLs de pics et ajoutez même ... Je me suis perdu ... mais merci quand même :) – Asaf

+0

+1 pour la seule réponse qui ne change pas l'entrée ou utilise un modèle de brique. @Asaf: Bien sûr, c'est une solution élégante, mais il n'y a pas de "magie" impliquer. De plus, la préférence pour les instructions 'xsl: for-each' sur' xsl: apply-templates' n'est pas un privilège débutant XSLT, c'est parce qu'il y a une mauvaise compréhension du paradigme déclaratif. –

+0

@Alejandro: Merci, votre opinion est la plus appréciée. @Asaf: vous risquez de rester débutant pendant une période looooong si vous ne vous efforcez pas d'apprendre. –

Questions connexes