2008-11-04 12 views
10

Descargo de responsabilidad: el siguiente es un pecado contra XML. Es por eso que estoy tratando de cambiar con XSLT :)Preservar espacios en blanco de atributos

Mi XML actualmente tiene el siguiente aspecto:

<root> 
    <object name="blarg" property1="shablarg" property2="werg".../> 
    <object name="yetanotherobject" .../> 
</root> 

Sí, estoy poniendo todos los datos de texto en atributos. Espero que XSLT pueda salvarme; Quiero avanzar hacia algo como esto:

<root> 
    <object> 
     <name>blarg</name> 
     <property1>shablarg</name> 
     ... 
    </object> 
    <object> 
     ... 
    </object> 
</root> 

De hecho, tengo todo este trabajo hasta ahora, con la excepción de que mis pecados contra XML han sido más ... excepcional. Algunas de las etiquetas de tener este aspecto:

<object description = "This is the first line 

This is the third line. That second line full of whitespace is meaningful"/> 

estoy usando xsltproc bajo Linux, pero no parecen tener ninguna opción para preservar los espacios en blanco. Intenté usar xsl: preserve-space y xml: space = "preserve" en vano. Cada opción que he encontrado parece aplicarse para mantener el espacio en blanco dentro de los elementos, pero no los atributos. Cada vez, lo anterior se cambia a:

 
This is the first line This is the third line. That second line full of whitespace is meaningful 

Así que la pregunta es, ¿puedo conservar el espacio en blanco atributo?

+0

se deben sustituir los espacios en blanco con las referencias de entidades de dentro del valor attribe, como reemplazar '' con ''. La normalización del valor del atributo (3.3.3) depende del tipo de atributo que creo que es 'CDATA' por defatult. Sin embargo, creo que puede forzarlo con ' '>' - puede o no ser correcto. Entonces, si tienes un XSL debes asegurarte de manejar tu espacio en blanco manualmente, hice de manera similar a 'string-join()' y 'tokenize()'. – n611x007

+0

*** Se puede hacer. *** Puede obtener un ejemplo completo ([SSCCE] (http://www.sscce.org/ "Corto, Autónomo, Correcto (Compilable), Ejemplo") fuera de mi respuesta a otra pregunta: http://stackoverflow.com/a/29780972/611007 (Como expliqué anteriormente, no es la forma en que tratas de hacerlo, pero al final, funcionará como te gustaría). – n611x007

+0

relacionado: https://stackoverflow.com/questions/449627/ - relacionado: https://stackoverflow.com/questions/2004386/ - relacionado: https://stackoverflow.com/questions/1289524/ – n611x007

Respuesta

5

Esto es en realidad un problema de análisis XML sin procesar, no algo con lo que XSLT pueda ayudarlo. Un análisis XML debe convertir los nuevos renglones en ese valor de atributo en espacios, según '3.3.3 Attribute-Value Normalization' en el estándar XML. Entonces, cualquier cosa que actualmente lea sus atributos de descripción y mantenga las líneas nuevas es hacerlo mal.

Puede recuperar las líneas nuevas preprocesando el XML para escapar de las líneas nuevas al & # 10; referencias de personaje, siempre y cuando no tenga líneas nuevas donde no se permiten charrefs, como cuerpos de etiquetas interiores. Charrefs debe sobrevivir como caracteres de control hasta el valor del atributo, donde puede convertirlos en nodos de texto.

+1

No estoy seguro de que esto funcione. Los Charrefs se reemplazan por los bytes que representan mediante el procesador XML, por lo que un carácter que se refiere a un carácter de espacio en blanco (como LINE FEED) se normalizará como espacio en blanco. – ChuckB

+1

El estándar y DOM Test Suite dicen que funciona; Su implementación puede variar, pero las que he probado lo hacen. – bobince

+0

@ChuckB Creo que depende * si puede controlar su procesador xml *. Puedo crear un buen resultado con un '.xsl' que funciona tanto en saxon como en firefox. – n611x007

3

De acuerdo con Annotated XML Spec, el espacio en blanco en los valores de los atributos es normalizado por el procesador XML (Ver la anotación (T) en 3.3.3). Entonces, parece que la respuesta es probablemente no.

+0

a menos que puedes controlar tu procesador xml – n611x007

1

Como han señalado otros, la especificación XML no permite la preservación de espacios en los atributos. De hecho, este es uno de los pocos diferenciadores entre lo que puede hacer con los atributos y los elementos (el otro principal es que los elementos pueden contener otras etiquetas mientras que los atributos no).

Primero deberá procesar el archivo fuera de XML para conservar los espacios.

+0

Creo que esto es engañoso. Si puede controlar su procesador xml, en sí mismo parece válido y posible conservar ese espacio en blanco. Pude lograr el resultado. – n611x007

0

Si puede controlar su procesador XML, puede hacerlo.

Desde mi other answer (que tiene muchas referencias vinculadas):

si tiene un XML como

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<!DOCTYPE elemke [ 
<!ATTLIST brush wood CDATA #REQUIRED> 
]> 

<elemke> 
<brush wood="guy&#xA;threep"/> 
</elemke> 

y un XSL como

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:template name="split"> 
    <xsl:param name="list"  select="''" /> 
    <xsl:param name="separator" select="'&#xA;'" /> 
    <xsl:if test="not($list = '' or $separator = '')"> 
    <xsl:variable name="head" select="substring-before(concat($list, $separator), $separator)" /> 
    <xsl:variable name="tail" select="substring-after($list, $separator)" /> 

    <xsl:value-of select="$head"/> 
    <br/><xsl:text>&#xA;</xsl:text> 
    <xsl:call-template name="split"> 
     <xsl:with-param name="list"  select="$tail" /> 
     <xsl:with-param name="separator" select="$separator" /> 
    </xsl:call-template> 
    </xsl:if> 
</xsl:template> 


<xsl:template match="brush"> 
    <html> 
    <xsl:call-template name="split"> 
    <xsl:with-param name="list" select="@wood"/> 
    </xsl:call-template> 
    </html> 
</xsl:template> 

</xsl:stylesheet> 

se puede obtener un HTML como:

<html>guy<br> 
    threep<br> 

</html> 

como probado/produjo con un procesador como saxon esta línea de comandos:

java -jar saxon9he.jar -s:in.xml -xsl:in.xsl -o:out.html 
+0

el 'ATTLIST' y el' DOCTYPE' aquí no son necesarios, CDATA sería el 'tipo de atributo' predeterminado para este ['AttValue'] (http://www.jelks.nu/XML/xmlebnf.html#NT- AttValue) aquí. – n611x007

+0

FYI una publicación aleatoria en procesador vs analizador: http://www.oxygenxml.com/archives/xsl-list/200009/msg00750.html – n611x007

+0

Crédito a [Tomalak] (https://stackoverflow.com/a/2850181/ 611007) para la plantilla 'cadena' porque en mi procesador xml de destino ['tokenize'] (http://www.w3.org/TR/xpath-functions/#func-tokenize) no estaba disponible. – n611x007

Cuestiones relacionadas