2010-08-08 17 views
7

mi piacerebbe utilizzare un file XMLCome ottenere il percorso di immagini per <img src="?"> tag dal file 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> 

in una tabella 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> 

cosa è il modo migliore per farlo?

+0

Buona domanda (+1). Vedi la mia risposta per una soluzione completa che è nello spirito di XSLT e per una spiegazione di tutti i momenti significativi della soluzione. :) –

risposta

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> 

Provate voi stessi qui (copia e incolla il mio codice in caselle appropriate):

+0

Questo non ha a che fare con la parte più difficile (organizzare le colonne della tabella), è troppo dettagliato ('' ha lo stesso risultato) ed è buggy dato che non puoi avere un elemento immagine senza un attributo alt e non puoi avere un elemento immagine come figlio di un elemento body. –

+1

@Jon: lasciatemi indirizzare i tuoi commenti. ** 1. ** organizzare la tabella html è banale, ho pensato che potesse capire quella parte, ma per te ho aggiornato il mio esempio per fare esattamente quello che sta cercando di ottenere (testarlo tu stesso) ** 2. ** il tuo esempio è molto più complicato del mio, soprattutto per chi inizia con XSLT, il mio fa quello che deve fare ed è semplice ** 3. ** Non vedo come sia bug, puoi mettere il 'img' ovunque, il mio esempio ** funziona! ** Sono confuso sul motivo per cui hai votato. Buona giornata. – JohnB

+1

Sono d'accordo con JohnB - a mio parere, la soluzione semplice è sempre migliore, soprattutto se stai iniziando a imparare una nuova tecnologia - cercare di padroneggiare il concetto è abbastanza difficile senza dover calpestare la criptica stenografia - dico sempre - "mantienilo semplice stupido " – Doug

1

Utilizzare XSL. Esempio here. Perché hai l'attributo no lì?

+1

Ovviamente, è anche taggato come [xslt] ... – kennytm

2

C'è un bug nel uscita suggerita, come <img/> elementi devono avere alt attributi in ogni versione di HTML, in cui sono presenti.

In ogni caso ciò che segue è questo, ma senza quegli attributi che possono essere fatti da CSS invece (solo per mantenere le dimensioni in giù). L'aggiunta di nuovo in se lo si desidera è banale:

<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> 

È possibile che questo presuppone che si desidera che il percorso dal file utilizzato direttamente, l'aggiunta di codice per trasformarlo in qualche modo (dire prendendo solo l'ultima parte del percorso utilizzando substring-after()) non è un'estensione difficile, supponendo che la trasformazione non sia complicata.

Edit:

Io e JohnB stanno andando in ulteriori territori qui, i suffissi di cui sopra per rispondere alla domanda iniziale.

Aggiunto per dare una risposta più completa alla domanda di JohnB. Quanto segue è il codice equivalente che utilizza per-invece di template di applicazione. In teoria, un'implementazione sequenziale e basata sullo stato macchina di un processore XSLT dovrebbe comportarsi in modo identico, anche se potresti trovare differenze nella pratica (se tu mi dicessi che erano diversi con un determinato processore, scommetterei una piccola somma su di esso essere leggermente più veloce con l'elaborazione sequenziale e leggermente più lento con l'elaborazione a macchina di stato, ma scommetterei solo una piccola quantità).

Si noti che non è possibile riutilizzare il modello predefinito per l'immagine. Sul lato positivo, se abbiamo un diverso modello predefinito per le immagini altrove (se questo fosse parte di un foglio di stile molto più complicato), non abbiamo bisogno di essere intelligenti per distinguere tra loro, che è il momento principale in cui personalmente si inclinerebbe verso-ciascuno.

<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 molto intelligente per generare le colonne! Non ho mai fatto niente di così carino con XSLT. Ma non hai bisogno di un ciclo attorno al ''? – JohnB

+0

Non abbiamo bisogno di un ciclo, perché i modelli di applicazione nella tabella eseguiranno ogni terza immagine in ordine e quindi verrà eseguito il modello appropriato, che a sua volta si occuperà dei due successivi. O per guardarlo in un altro modo, apply-templates è un ciclo, anche se a volte un ciclo su un solo oggetto. C'è ben poco (se non altro) che si può fare con-ogni cosa che non si può fare con i modelli di applicazione e viceversa. Normalmente la differenza riguarda ciò che sembra più naturale al momento, che dipende in qualche modo dallo stile del programmatore. Mi rivolgo ai modelli di applicazione come probabilmente più dichiarativi e più propensi a riutilizzarli. –

+0

@JohnB Ho aggiunto un'implementazione for-each e una spiegazione della differenza per rispondere in modo più completo a tale domanda. –

0

Ecco una tipica soluzione che aderisce allo spirito di XSLT (senza <xsl:for-each>), il più breve possibile, e parametrizzato il numero desiderato di colonne della tabella.

<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> 

Quando questa trasformazione viene applicata sul seguente documento XML (sulla base del documento XML fornito, ma con altre immagini che sono davvero colorato e interessante):

<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> 

il risultato voluto è prodotto (vedere anche in un browser :)):

<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> 

Do atto:

  1. L'uso dell'operatore XPath mod per determinare gli elementi di ogni riga.

  2. L'uso di modalità per elaborare lo stesso tipo di elemento (<pic>) in due modi diversi.

  3. L'uso di AVT (attributo-valore-modelli) per rendere il codice più breve e più comprensibile.

+0

Sembra molto elegante ... ma io sono meno che un principiante - non ho mai avuto il tempo di capire la magia di xslt. Ho provato a copiare e incollare il codice, modificare gli URL delle immagini e persino aggiungere ... Mi sono perso ... ma grazie comunque :) – Asaf

+0

+1 per la sola risposta che non modifica l'input o usa un modello di mattone. @Asaf: Ovviamente questa è una soluzione elegante, ma non c'è alcun coinvolgimento "magico". Inoltre, la preferenza per le istruzioni 'xsl: for-each' su' xsl: apply-templates' non è un privilegio per principianti XSLT, è perché c'è qualche errore nel paradigma dichiarativo. –

+0

@ Alejandro: Grazie, la tua opinione è molto apprezzata. @Asaf: rischi di rimanere un principiante per un tempo lunghissimo se non ti sforzi di imparare. –

Problemi correlati