xslt - when - Insertando un salto de línea en un PDF generado desde XSL FO usando<xsl: value-of>
xslt online (11)
Estoy utilizando XSL FO para generar un archivo PDF que contiene una tabla con información. Una de estas columnas es una columna de "Descripción". Un ejemplo de una cadena con la que estoy rellenando uno de estos campos de Descripción es el siguiente:
This is an example Description.<br/>List item 1<br/>List item 2<br/>List item 3<br/>List item 4
Dentro de la celda de la tabla que corresponde a esta Descripción, me gustaría que la salida se muestre como tal:
This is an example Description.
List item 1
List item 2
List item 3
List item 4
Aprendí de buscar en otra parte que puedes hacer saltos de línea en XSL FO usando un <fo:block></fo:block>
dentro de otro elemento <fo:block>
. Por lo tanto, incluso antes de analizar el XML con mi hoja de estilo XSL, sustituyo todas las apariciones de <br/>
con <fo:block/>
, para que el valor literal de la cadena ahora se vea como:
This is an example Description.<fo:block/>List item 1<fo:block/>List item 2<fo:block/>List item 3<fo:block/>List item 4
El problema surge cuando la cadena de descripción que estoy usando se obtiene usando <xsl:value-of>
, ejemplo de la siguiente manera:
<fo:block>
<xsl:value-of select="descriptionStr"/>
</fo:block>
En cuyo caso, el valor que se imprime en mi documento PDF es el valor literal, por lo que se ve exactamente como el ejemplo anterior con todos los literales <fo:block/>
. He intentado codificar manualmente el <fo:block/>
en medio de otra cadena, y se muestra correctamente. Por ejemplo, si escribo dentro de mi hoja de estilo:
<fo:block>Te<fo:block/>st</fo:block>
Se mostrará correctamente como:
Te
st
Pero esto no parece suceder cuando <fo:block/>
está dentro del valor de una declaración <xsl:value-of select=""/>
. He intentado buscar esto en SO así como en Google, etc. sin éxito. Cualquier consejo o ayuda será muy apreciado. ¡Gracias!
Para XSLT 1.0, estoy usando mi plantilla de salto de línea XSLT en GitHub.
Para XSL-FO soporta
- Saltos de línea
- Delimitadores de línea (frente a saltos de línea)
- Serie de punteros en una fila.
- Ignorar repeticiones de puntero (deshabilite la serie de punteros en una fila)
- Cualquier cadena como puntero para insertar una ruptura o un delimitador ("/ n" es predeterminado)
- Línea de delimitadores de altura.
- Altura delimitadora de línea predeterminada de un tamaño de fuente actual.
- Ignorar automáticamente el carácter "/ r" cuando se busca un lugar de descanso.
- Se agregó soporte para XSLT 2.0 para una migración sin problemas.
- algo más...
Para XSLT 2.0 y versiones posteriores, considere utilizar enfoques como
- XSLT 2.0 xsl: analizar-cadena (RegEx)
- XPath 2.0 tokenize + XSLT (RegEx)
- pasar secuencias como un parámetro de plantilla (XSLT 2.0)
- y así
El siguiente código funcionó:
<fo:block white-space-collapse="false"
white-space-treatment="preserve"
font-size="0pt" line-height="15px">.</fo:block>
Hace que el procesador xsl piense que este bloque contiene una línea de texto, que en realidad tiene un tamaño de fuente 0pt. Puede personalizar la altura de la línea proporcionando su propio valor.
Esto me ayudó y debería ser la solución más sencilla (trabajar con Apache FOP 1.1):
¿Por qué no reemplazar su <br/>
con un carácter de Unicode llamado separador de línea .
<xsl:template match="br">
<xsl:value-of select="''
''"/>
</xsl:template>
Generar cadenas que contengan marcas XML escapadas rara vez es la respuesta correcta, pero si eso es con lo que tienes que trabajar, entonces para una entrada como esta:
<Description><![CDATA[This is an example Description.<br/>List item 1<br/>List item 2<br/>List item 3<br/>List item 4]]></Description>
Si está usando XSLT 2.0, puede usar xsl:analyze-string
para obtener el fo:block
vacío que originalmente quería:
<xsl:template match="Description">
<fo:block>
<xsl:analyze-string select="." regex="<br/>">
<xsl:matching-substring>
<fo:block />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</fo:block>
</xsl:template>
pero si está utilizando XSLT 2.0, puede usar de forma más concisa linefeed-treatment="preserve"
según @Daniel Haley y usar replace()
para insertar las líneas de alimentación:
<xsl:template match="Description">
<fo:block linefeed-treatment="preserve">
<xsl:value-of select="replace(., ''<br/>'', ''
'')" />
</fo:block>
</xsl:template>
Si está utilizando XSLT 1.0, puede retroceder a través de la cadena:
<xsl:template match="Description">
<fo:block linefeed-treatment="preserve">
<xsl:call-template name="replace-br" />
</fo:block>
</xsl:template>
<xsl:template name="replace-br">
<xsl:param name="text" select="." />
<xsl:choose>
<xsl:when test="not(contains($text, ''<br/>''))">
<xsl:value-of select="$text" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before($text, ''<br/>'')"/>
<xsl:text>
</xsl:text> <!-- or <fo:block /> -->
<xsl:call-template name="replace-br">
<xsl:with-param name="text" select="substring-after($text, ''<br/>'')"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Intente usar linefeed-treatment = "preserve" y / n en lugar de <br>
para una nueva línea.
<fo:block linefeed-treatment="preserve" >
<xsl:value-of select="Description" />
</fo:block>
No debe usar xsl:value-of
instrucción, sino xsl:apply-templates
lugar: para la regla incorporada para el nodo de texto solo se mostrará su valor de cadena, y para el elemento br
vacío podría declarar una regla que coincida con descriptionStr/br
o descriptionStr//br
(dependiendo de tu entrada) para transformar en vacío fo:block
.
Prueba esto:
<fo:block><fo:inline color="transparent">x</fo:inline></fo:block>
Este código agrega un bloque que contiene texto transparente, por lo que parece una nueva línea.
También puede reemplazar <br/>
con 

y agrega un atributo linefeed-treatment="preserve"
a tu <fo:block>
.
Algo como:
<fo:block linefeed-treatment="preserve">This is an example Description.
List item 1
List item 2
List item 3
List item 4</fo:block>
Editar
Es posible que algunos usuarios necesiten usar /n
lugar de 

Dependiendo de cómo estén creando el XML. Consulte Retener el & # xA; durante la ordenación xml para más detalles.
Tuve un bloque de texto que se ve así
<fo:table-cell display-align="right">
<fo:block font-size="40pt" text-align="right">
<xsl:text> Text 1 </xsl:text>
<fo:block> </fo:block>
<xsl:text> Text2 </xsl:text>
<fo:block> </fo:block>
<xsl:text> Text 3</xsl:text>
</fo:block>
NB: tenga en cuenta el vacío
Usualmente uso un bloque vacío con una altura que se puede cambiar si necesito más o menos espacio:
<fo:block padding-top="5mm" />
Sé que esta no es la mejor solución, pero es funcional.
</fo:block>
en sí mismo no es un sustituto directo de <br/>
<br/>
es una aberración no pareada html que no tiene un equivalente directo en xsl: fo
</fo:block>
solo significa el final del bloque. Si los dispersa a través de su texto, no tendrá un xml válido, y su procesador xsl causará errores.
Para el formato de salto de línea que desee, cada bloque se producirá en una nueva línea. Necesita un <fo:block>
inicio </fo:block>
un par de bloque de final </fo:block>
para cada línea.