27 votos

XSLT - quitar espacios en blanco de la plantilla

Estoy usando XML para almacenar una pequeña lista de contactos y tratando de escribir una plantilla XSL que la transformará en un archivo CSV. El problema que estoy teniendo es con los espacios en blanco en la salida.

El resultado:

Friend, John, Smith, Home,
    	123 test,
       Sebastopol,
       California,
       12345,
     Home 1-800-123-4567, Personal john.smith@gmail.com

He sangría/espaciados tanto el XML de origen y el fichero de asociados Plantilla XSL para hacer más fácil la lectura y desarrollar, pero todo lo que el espacio en blanco adicional es llegar a sí mismo en la salida. El XML no tiene un espacio en blanco adicional dentro de los nodos, en las afueras de ellos para el formato, y lo mismo va para el XSLT.

En orden para el archivo CSV para que sea válida, cada entrada debe estar en su propia línea, no roto. Además de recortar todo el espacio en blanco adicional de XML y XSLT (lo que en una larga línea de código), hay otra manera de deshacerse de los espacios en blanco en la salida?

Editar: He aquí un pequeño ejemplo de código XML:

<PHONEBOOK>
    <LISTING>
    	<FIRST>John</FIRST>
    	<LAST>Smith</LAST>
    	<ADDRESS TYPE="Home">
    		<STREET>123 test</STREET>
    		<CITY>Sebastopol</CITY>
    		<STATE>California</STATE>
    		<ZIP>12345</ZIP>
    	</ADDRESS>
    	<PHONE>1-800-123-4567</PHONE>
    	<EMAIL>john.smith@gmail.com</EMAIL>
    	<RELATION>Friend</RELATION>
    </LISTING>
</PHONEBOOK>

Y aquí está el XSLT:

<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />

 <xsl:template match="/">
   <xsl:for-each select="//LISTING">
    <xsl:value-of select="RELATION" /><xsl:text>, </xsl:text>
    <xsl:value-of select="FIRST" /><xsl:text>, </xsl:text>
    <xsl:value-of select="LAST" /><xsl:text>, </xsl:text>

    <xsl:if test="ADDRESS">
     <xsl:for-each select="ADDRESS">
       <xsl:choose>
    	<xsl:when test="@TYPE">
    	 <xsl:value-of select="@TYPE" />,
    	</xsl:when>
    		<xsl:otherwise>
    		<xsl:text>Home </xsl:text>
    		</xsl:otherwise>
       </xsl:choose>
       <xsl:value-of select="STREET" />,
       <xsl:value-of select="CITY" />,
       <xsl:value-of select="STATE" />,
       <xsl:value-of select="ZIP" />,
     </xsl:for-each>
    </xsl:if>

    <xsl:for-each select="PHONE">
      <xsl:choose>
       <xsl:when test="@TYPE">
    	<xsl:value-of select="@TYPE" />  
       </xsl:when>
       <xsl:otherwise><xsl:text>Home </xsl:text></xsl:otherwise>
      </xsl:choose>
     <xsl:value-of select="."  /><xsl:text  >, </xsl:text>
    </xsl:for-each>

    <xsl:if test="EMAIL">
     <xsl:for-each select="EMAIL">
      <xsl:choose>
       <xsl:when test="@TYPE">
    	<xsl:value-of select="@TYPE" /><xsl:text  > </xsl:text> 
       </xsl:when>
       <xsl:otherwise><xsl:text  >Personal </xsl:text></xsl:otherwise>
      </xsl:choose>
      <xsl:value-of select="."  /><xsl:text  >, </xsl:text>
     </xsl:for-each>
    </xsl:if>
    <xsl:text>&#10;&#13;</xsl:text>
   </xsl:for-each>
 </xsl:template>

</xsl:stylesheet>

58voto

Tomalak Puntos 150423

En XSLT, espacio en blanco se conserva de forma predeterminada, ya que puede ser muy pertinente de los datos.

La mejor manera de evitar los indeseados de espacio en blanco en la salida no es crear en el primer lugar. No hacer:

<xsl:template match="foo">
  foo
</xsl:template>

debido a que el "\n··foo\n", desde el procesador de punto de vista. En lugar de hacer

<xsl:template match="foo">
  <xsl:text>foo</xsl:text>
</xsl:template>

Espacio en blanco en la hoja de estilos se ignora el tiempo que se produce entre los elementos XML sólo. En pocas palabras: nunca use el "desnudo" de texto en cualquier lugar en el código XSLT, siempre encerrarlo en un elemento.

Además, el uso de una vaga:

<xsl:apply-templates />

es problemático, debido a que por defecto XSLT regla de los nodos de texto que dice "copia de ellos a la salida". Esto se aplica a "espacio en blanco" sólo los nodos. Por ejemplo:

<xml>
  <data> value </data>
</xml>

contiene tres nodos de texto:

  1. "\n··" (a la derecha después de la <xml>)
  2. "·value·"
  3. "\n" (justo antes de </xml>)

Para evitar que #1 y #3 colarse en la salida (que es la razón más común para espacios no deseados), puede reemplazar el valor predeterminado de la regla de los nodos de texto mediante la declaración de una plantilla vacía:

<xsl:template match="text()" />

Todos los nodos de texto son ahora silenciado y salida de texto deben ser creadas explícitamente:

<xsl:value-of select="data" />

Para eliminar el espacio en blanco de un valor, se podría utilizar el normalize-space() función XSLT:

<xsl:value-of select="normalize-space(data)" />

Pero cuidado, ya que la función normaliza cualquier espacio en blanco se encuentra en la cadena, por ejemplo "·value··1·" volvería "value·1".

Además se puede utilizar el <xsl:strip-space> y <xsl:preserve-space> elementos, aunque por lo general esto no es necesario (y personalmente, prefiero explícita control de espacios en blanco como se indicó anteriormente).

4voto

Noah Heldman Puntos 2817

De forma predeterminada, las plantillas XSLT tienen <xsl:preserve-space> set, que va a mantener los espacios en blanco en su salida. Usted puede agregar <xsl:strip-space elements="*"> a decirle que donde para eliminar los espacios en blanco.

Usted también puede necesitar incluir un normalizar el espacio de la directiva, así:

<xsl:template match="text()"><xsl:value-of select="normalize-space(.)"/></xsl:template> 

Aquí está un ejemplo para preservar/tira espacio de W3 Schools.

1voto

David Andres Puntos 13569

Tan lejos como la eliminación de pestañas, pero la retención de líneas separadas, he intentado de la siguiente XSLT 1.0 enfoque, y funciona bastante bien. El uso de la versión 1.0 o 2.0 depende en gran medida de la plataforma que estamos utilizando. Como se ve .NETO de la tecnología es todavía depende de XSLT 1.0, y por lo que está limitado a muy desordenado plantillas (ver más abajo). Si usted está usando Java o algo más, por favor refiérase a la mucho más limpio XSLT 2.0 enfoque en la lista hacia la parte inferior.

Estos ejemplos tienen el propósito de ser ampliado para satisfacer sus necesidades específicas. Estoy usando fichas aquí como un ejemplo, pero este debe ser lo suficientemente genérica como para ser extensible.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<text>
        adslfjksdaf

        		dsalkfjdsaflkj

        	lkasdfjlsdkfaj
</text>

...y el XSLT 1.0 plantilla (necesario si se utiliza .NET):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet  
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">   
 <xsl:template name="search-and-replace">
   <xsl:param name="input"/>
   <xsl:param name="search-string"/>
   <xsl:param name="replace-string"/>
   <xsl:choose>
    <xsl:when test="$search-string and 
                    contains($input,$search-string)">
       <xsl:value-of
           select="substring-before($input,$search-string)"/>
       <xsl:value-of select="$replace-string"/>
       <xsl:call-template name="search-and-replace">
         <xsl:with-param name="input"
               select="substring-after($input,$search-string)"/>
         <xsl:with-param name="search-string"
               select="$search-string"/>
         <xsl:with-param name="replace-string"
               select="$replace-string"/>
       </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$input"/>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:template>                
  <xsl:template match="text">
   <xsl:call-template name="search-and-replace">
     <xsl:with-param name="input" select="text()" />
     <xsl:with-param name="search-string" select="'&#x9;'" />
     <xsl:with-param name="replace-string" select="''" />
   </xsl:call-template>    
  </xsl:template>
</xsl:stylesheet>

XSLT 2.0 hace que este trivial con la replace función de:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      exclude-result-prefixes="xs"
      version="2.0">
 <xsl:template match="text">
  <xsl:value-of select="replace(text(), '&#x9;', '')" />
 </xsl:template>
</xsl:stylesheet>

1voto

Pavel Minaev Puntos 60647

Otros ya han señalado el problema general. Específica para su hoja de estilo es que se le olvidó <xsl:text> por comas:

   <xsl:choose>
    <xsl:when test="@TYPE">
     <xsl:value-of select="@TYPE" />,
    </xsl:when>
    <xsl:otherwise>Home </xsl:otherwise>
   </xsl:choose>
   <xsl:value-of select="STREET" />,
   <xsl:value-of select="CITY" />,
   <xsl:value-of select="STATE" />,
   <xsl:value-of select="ZIP" />,

Esto hace que el espacio en blanco después de cada coma significativa, y por lo que termina en la salida. Si la envoltura de cada coma, en <xsl:text>, el problema desaparece.

También, deshacerse de ese disable-output-escaping. No hacer nada aquí, ya no está la salida XML.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X