Creazione di una XSL ricorsiva: se l'istruzione?
-
06-07-2019 - |
Domanda
Sto cercando di impostare un'istruzione XSL: IF che mostra solo le voci che hanno un nodo compreso tra due valori. Abbastanza semplice, vero? È solo un se maggiore di e se minore di. Il problema è che, invece di testarlo su un nodo, devo testarlo fino a un massimo di 52.
Diciamo che ho un po 'di XML simile a questo:
<container>
<entry>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
<item>6</item>
<item>7</item>
<item>8</item>
<item>9</item>
<item>10</item>
</entry>
</container>
Ora dì che mi viene dato un intervallo di 9 & # 8211; 15. Poiché alcuni dei nodi rientrano in tale intervallo, voglio visualizzare quella voce. Ma se mi venisse dato un intervallo di 11 & # 8211; 15 nessuno dei nodi si adattava quindi non vorrei che fosse visualizzato.
Il problema è ... Non ho assolutamente idea di come lo faresti. So che puoi IF un singolo valore ma non riesco a pensare a un modo semplice per testare ciascun nodo.
A proposito, tutto questo viene fatto all'interno dell'ultima versione stabile del Symphony CMS.
[modifica] Il problema con i primi due risultati è che visualizzano i nodi ITEM, quello che sto cercando è di restituire solo nodi ENTRY che hanno almeno un nodo ITEM corrispondente. Non sono sicuro di come una delle soluzioni possa aiutare questo.
Soluzione
Puoi farlo utilizzando un predicato nidificato nelle <entry>
corrispondenze:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:for-each select="container/entry[item[number(.) >= 9 and number(.) <= 15]]">
<!-- this will loop over <entry>s which contain <item>s within your range -->
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
L'espressione verrebbe letta come " voci che contengono elementi i cui valori sono compresi tra 9 e 15 " ;.
Altri suggerimenti
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:copy-of select="container/entry/item[number(.) >= 9 and number(.) <= 15]"/>
</xsl:template>
</xsl:stylesheet>
L'istruzione XPath 'container / entry / item' si riferisce a tutti gli articoli corrispondenti. Il predicato [numero (.) & Gt; = 9 e numero (.) & Lt; = 15] analizza l'elenco in basso. Alcune operazioni XSLT (ad es. Xsl: value-of) hanno un filtro implicito che prende solo il primo valore. In questi casi, puoi usare xsl: for-each:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:for-each select="container/entry/item[number(.) >= 9 and number(.) < 15]">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Che ne dici di questo .... Puoi fare quello che vuoi all'interno del ciclo for-each oppure puoi semplicemente prendere il nodeset restituito nella variabile e usarlo da qualche altra parte.
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<!-- Your first param -->
<xsl:param name="Param1" select="4"/>
<!-- Your second param -->
<xsl:param name="Param2" select="9"/>
<xsl:variable name="ResultNodeSet">
<xsl:for-each select="/container/entry/item[number(.) >= $Param1 and number(.) <= $Param2]">
<!-- What ever else you want to do can go here-->
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$ResultNodeSet"/>
</xsl:template>
</xsl:stylesheet>