PDA

View Full Version : Trasformazione xml -> html con xslt


anx721
20-08-2004, 23:34
Ho un problema con un processore xslt (saxon 6.5.3) che sembra eseguire male l'iterazione con il for; io gli dico di iterare per ogni nodo <item> del nodo corrente e di produrre per ciascuno un blocco <li>...<li> in una lista; ma alla fine mi trovo una lista con molti piu elementi di quelli elencati nel documento xml; se visualizzo il file xml direttamente con Internet Explorer me lo visualizza correttamente, mentre con FireFox ottengo lo stesso risultato di saxon. Questo è il file a.xml:


<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="a.xsl"?>

<document>
<list>
<item>1</item>
<item>2</item>
<item>3</item>
</list>
</document>


e questo il file a.xsl:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html><body>
<xsl:apply-templates select="//list"/>
</body></html>
</xsl:template>


<xsl:template match="list">
<ul>
<xsl:for-each select="node()">
<li>elemento
<xsl:apply-templates select="." />
</li>
</xsl:for-each>
</ul>
</xsl:template>

</xsl:stylesheet>


e il risultato prodotto, notate che tutti li elementi della lista corretti sono intervallati da elementi in piu (nei quali c'è solo il testo 'elemento' senza il numero):


<html>
<body>

<ul>

<li>elemento
</li>

<li>elemento 1
</li>

<li>elemento
</li>

<li>elemento 2
</li>

<li>elemento
</li>

<li>elemento 3
</li>

<li>elemento
</li>

</ul>
</body>
</html>

Si tratta di un bug o sbalio io a scrivere? Mi sembra di aver letto che saxon è tra i processori piu diffusi, me ne sapete indicare qlcunaltro buono?

theClimber
22-08-2004, 12:29
con node() identifichi anche i nodi di testo vuoti, presenti tra un item e l'altro, come da specifica W3C:
node() matches any node other than an attribute node and the root node
Sembra quindi che il contenuto del ciclo viene eseguito non solo per i nodi item, ma anche per i nodi di testo vuotiche servono per andare a capo tra un item e l'altro.... Infatti ce ne sono 4 di elementi senza numero, come 4 sono i nodi di spazi vuoti intorno agli elementi <item>.

Secondo specifica questi nodi vuoti dovrebbero essere eliminati in fase di parsing, a meno di esplicite direttive per preservarli. Non e' che hai settato qualche direttiva in SAXON x modificare questo?

In alternativa prova con il seguente codice (che ti evita anche il ciclo for, che personalmente ritengo da evitare se possibile in XSLT :D)

.....
<xsl:template match="list">
<ul>
<xsl:apply-templates/>
</ul>
</xsl:template>

<xsl:template match="item">
<li>elemento <xsl:value-of select="."/></li>
</xsl:template>
.....


Originariamente inviato da anx721
Mi sembra di aver letto che saxon è tra i processori piu diffusi, me ne sapete indicare qlcunaltro buono?

Xalan:
http://xml.apache.org/xalan-j/index.html

Ciao

anx721
22-08-2004, 14:46
razie per la risposta, temevo di esserel'unico qui ad occuparmi di xslt...

In effetti avevo gia risolto mettendo * al posto di node(), e aveva funzionato, anche se non riuscivo a capire il comportamento di node(). Poi ci ero arrivato facendo un po di prove e inserendo del testo qua e la e avevo intuito qquel che faceva. In effetti mi ero gia scaricato anche xalan, e quando ho visto che mi produceva lo stesso output di saxon ho capito che ero io a sbagliare... La cosa strana era pero che Internet explorer mi visualizzava i risultati come volevo io, ingnorando le parti di testo, a differenza di firefox che invece mi ha fattoa ccorgere dell'errore.

il motivo per cui nonho utilizzato la forma:

<xsl:template match="item">
<li>elemento <xsl:value-of select="."/></li>
</xsl:template>

è perche in altri contesti <item> non deve essere trasformato in un <li>. probablemnte pero si poteva fare anche in altri modi senza il for, forse utilizzando i mode?

theClimber
22-08-2004, 20:16
Ottimo, in effetti con * si identificano i soli element, e non nodi generici che potrebbero essere anche di altri tipi.
Per essere + precisi, si potrebbe matchare solo gli elementi <item> , in modo che se si aggiungono ulteriori elementi differenti, non vengono inseriti nella lista di output

....
<xsl:for-each select="item">
...


Originariamente inviato da anx721
si poteva fare anche in altri modi senza il for, forse utilizzando i mode?

Si, nel caso devi presentare lo stesso elemento varie volte, il mode e' una buona scelta. L'unico inghippo a cui prestare attenzione e' che non si propaga automaticamente in caso di ulteriori subtemplates chiamati con apply-templates.

Ciao