Tengo un bloque de XSLT que puede aplicarse varias veces a lo largo de una transformación. Pero quiero que realmente se ejecute solo la primera vez que se aplica, se debe omitir todos los tiempos secundarios. ¿Cómo hago esto?En XSLT, puedo ejecutar una plantilla solo una vez
A modo de ejemplo, este es el tipo de cosas que quiero hacer: En la hoja de estilo defino una variable global:
<xsl:variable name="run_once" select="0"/>
entonces tengo una plantilla que se llama varias veces:
<xsl:template name="some_template">
<xsl:if test="$run_once != 1">
<xsl:variable name="run_once" select="1"/>
<xsl:text>THIS TEXT SHOULD APPEAR ONLY ONCE</xsl:text>
</xsl:if>
</xsl:template>
Esto no funciona, por supuesto, porque las variables no se pueden cambiar, solo se sobrecargan. Por lo tanto, una vez que some_template sale $ run_once vuelve a ser 0 y el texto se aplica cada vez que se llama a la plantilla. ¿Hay algún tipo de funcionalidad ifdef u otro objeto global que pueda establecer?
Si usted está interesado en saber por qué quiero hacer esto, a continuación es una explicación más detallada de mi problema y la solución utilicé:
- Mi entrada son datos en XML sin procesar, mi producción es una informe en formato WordML.
- En la entrada tengo una serie de nodos (llamado theNode). Algunos, pero no todos, de estos nodos deben ser en la salida. El nodo debe mostrarse solo si XPATH hairyLogic es verdadero (hairyLogic es obviamente largo y complejo).
- theNode también tienen un tipo (almacenado en un subnodo). En la entrada, todos theNode del mismo tipo serán siempre agrupados. En la salida , todos losNodo del mismo tipo deben agruparse bajo un encabezado específico para ese tipo (allí debe ser solo un encabezado para cada tipo ).
Esta es la solución que terminé usando:
...
<xsl:apply-templates select="theNode[hairyLogic]"/>
...
<xsl:template match="theNode">
<xsl:if test="count(preceding-sibling::theNode[type = current()/type and hairyLogic])=0">
<xsl:choose>
<xsl:when test="type = 'TYPE1a' or type = 'TYPE1b'">
<xsl:call-template name="TYPE1Heading"/>
</xsl:when>
<xsl:when test="type = 'TYPE2'">
<xsl:call-template name="TYPE2Heading"/>
</xsl:when>
</xsl:choose>
</xsl:if>
...
</xsl:template>
he elegido para usar plantillas con nombres de los encabezados, ya que contienen WordML básica que no depende de ningún dato en el XML de entrada.
No me gusta esta solución porque hairyLogic se repite y la sentencia if es intrincada y difícil de leer. ¿Tal vez tienes una mejor solución que no requiere variables mutables?
"¿cuál es el equivalente XSLT de pythonic? Xslt-y?" - es "declarativo" –
Sí, tengo restricciones que no detallé por completo (agregadas a la pregunta, si está interesado). Resolví el problema de la forma en que describes. No me gusta porque "Somelogic" es largo, desordenado, y ahora se repite varias veces. No sería tan malo si pudiera dictar cuando se analiza el código XPATH, como puedo en otros lenguajes funcionales. Entonces podría almacenar el bit malo de "somelogic" en una variable e insertarlo en mis expresiones cuando sea necesario. – oillio