XSLT / XPath: Selezione di un commento precedente
-
18-09-2019 - |
Domanda
Ho XML nel seguente formato, che voglio riformattare:
<blocks>
<!-- === apples === -->
<block name="block1">
...
</block>
<!-- === bananas === -->
<block name="block2">
...
</block>
<!-- === oranges === -->
<block name="block3">
...
</block>
</blocks>
Il mio problema è che non riesco a capire come selezionare le osservazioni di cui sopra ogni tag blocco. Ho il seguente XSL:
<xsl:template match="//blocks">
<xsl:apply-templates select="block" />
</xsl:template>
<xsl:template match="block">
<xsl:apply-templates select="../comment()[following-sibling::block[@name = ./@name]]" />
<xsl:value-of select="./@name" />
</xsl:template>
<xsl:template match="comment()[following-sibling::block]">
<xsl:value-of select="."></xsl:value-of>
</xsl:template>
L'output che sto provando per è:
=== === mele
Blocco1
=== === banane
blocco2
=== === arance
block3
Ma il meglio che posso ottenere è:
=== === mele
=== === banane
=== === arance
Blocco1
=== === mele
=== === banane
=== === arance
blocco2
=== === mele
=== === banane
=== === arance
block3
Sto usando PHP se questo fa alcuna differenza.
Soluzione
È possibile applicare i modelli per i commenti anche nei vostri primi apply-templates al posto del secondo, in modo che succede in ordine - Inoltre, questa soluzione dipende l'ordine dei dati nel XML di origine ..
<xsl:template match="//blocks">
<xsl:apply-templates select="block | comment()" />
</xsl:template>
PS: -. Si poteva evitare di usare "//" nelle espressioni come può essere non ottimale
[EDIT] Completa foglio di stile
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="//blocks">
<xsl:apply-templates select="block | comment()"/>
</xsl:template>
<xsl:template match="block">
<xsl:value-of select="./@name"/>
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Aggiungere la seguente istruzione se si vuole a capo, dopo aver stampato il valore sia in blocco e il commento.
<xsl:text> </xsl:text>
Altri suggerimenti
Il tuo foglio di stile è un po 'troppo complicato.
Si dovrebbe cercare il foglio di stile qui sotto e troverete che corrisponda l'uscita che si desidera!
<xsl:template match="//blocks">
<xsl:apply-templates select="block" />
</xsl:template>
<xsl:template match="block">
<xsl:apply-templates select="preceding-sibling::comment()[1]" />
<xsl:value-of select="./@name" />
</xsl:template>
<xsl:template match="comment()">
<xsl:value-of select="."></xsl:value-of>
</xsl:template>
Questo codice corrisponde sempre 1 o 0 commenti che partono proprio prima del tag di blocco attuale.