2010-03-17 17 views
14

Necesito eliminar los caracteres XML del interior de los nodos XML con la ayuda de solo las transformaciones XSLT. Tengo <text>&lt;&gt;and other possible characters</text> y necesito obtenerlo como HTML con formato válido cuando lo coloco dentro de la etiqueta del cuerpo.¿Cómo desacoplar caracteres XML con la ayuda de XSLT?

+0

No estoy seguro de que entiendo ... <y> son HTML válidos. ¿Estás diciendo que quieres convertirlos en partes de etiquetas HTML, p. transformar "<i> foo </i >" en " foo"? – wdebeaum

+0

¡Tienes toda la razón! – Artic

+0

Solo traté de hacer esto en XSL 1.0, y resultó ser realmente desagradable (2.0 podría ser un poco mejor, pero no es ampliamente compatible). A menos que pueda hacer el truco de desactivación de salida-escape, básicamente tiene que analizar el HTML en cada nodo de texto y construir recursivamente los elementos usando y . Suponiendo que se trata de un navegador web, tal vez podría hacerlo en JavaScript (o incluso en el lado del servidor)? – wdebeaum

Respuesta

35
<xsl:template match="text"> 
    <body> 
    <xsl:value-of select="." disable-output-escaping="yes" /> 
    </body> 
</xsl:template> 

Tenga en cuenta que la salida no se garantiza que sea XML bien formado ya.

+4

También señalaría que disable-output-escaping es una función de serialización opcional. No es compatible, por ejemplo, con el procesador XSLT utilizado en los navegadores Mozilla como Firefox, ya que estos procesan directamente el árbol de resultados y no lo serializan. –

+1

hola cuando
etiqueta se produjo en una cadena y luego disable-output-escaping = "yes" no funciona. –

1

No he encontrado una respuesta a esta pregunta. Entonces llegué a la conclusión de que esta no es forma de hacer esto. Encontré una solución para este problema, unescaping file en el lado del servidor.

+0

Erm ... ¿Qué pasa con mi respuesta? Esta * es * la manera de hacer lo que pide. – Tomalak

+0

Su sugerencia inhabilita el escapado de salida y necesitaba desactivar los símbolos como & nbsp en "". – Artic

+2

Qué es * exactamente * qué significa "deshabilitar el escape de salida". Si su entrada sería escapada correctamente, lo cual no es, tendría '<' y '>', y estos pasarían a '<' and '>'. Y entonces tendría '& nbsp;', que pasaría a ' '. Y esa es una secuencia de escape de HTML perfectamente legal que no necesita ninguna traducción adicional a "". El hecho de que tenga ' ' significa que su entrada está rota para empezar. – Tomalak

3

Con xslt 2.0 he creado esta. Tenga en cuenta que no se garantiza que el resultado sea xml correcto, una desigualdad simple puede estropear su salida.

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

<xsl:character-map name="a"> 
    <xsl:output-character character="&lt;" string="&lt;"/> 
    <xsl:output-character character="&gt;" string="&gt;"/> 
</xsl:character-map> 

<xsl:output use-character-maps="a"/> 

<xsl:template match="@*|node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
0

Otra solución. Éste no utiliza el postprocesador xml, tan fácilmente utilizable como entrada de un procesamiento xslt adicional. También se garantiza la creación de xml válido. Esta es una solución xslt 2.0, escapando texto dentro de etiquetas de "documentación", probado con saxon. Debe modificar la variable "allowedtags" para definir su propio modelo de datos. Los niños inmediatos son las etiquetas, los que están debajo de ellos son los atributos posibles. Leer las etiquetas permitidas de un xsd se deja como un ejercicio para el lector (por favor, compártelo conmigo).

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:fn="http://www.w3.org/2005/xpath-functions" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    xmlns:my="http://magwas.rulez.org/my" 
> 
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> 

<xsl:variable name="allowedtags"> 
<li/> 
<ul/> 
<br/> 
<a><href/></a> 
</xsl:variable> 

<xsl:template match="@*|*|processing-instruction()|comment()" mode="unescape"> 
    <xsl:copy> 
     <xsl:apply-templates select="*|@*|text()|processing-instruction()|comment()" mode="unescape"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="documentation" mode="unescape"> 
    <documentation> 
    <xsl:call-template name="doc"> 
     <xsl:with-param name="str"> 
      <xsl:value-of select="."/> 
     </xsl:with-param> 
    </xsl:call-template> 
    </documentation> 
</xsl:template> 

<xsl:template name="doc"> 
    <xsl:param name="str"/> 
    <xsl:variable name="start" select="fn:substring-before($str,'&lt;')"/> 
    <xsl:variable name="rest" select="fn:substring-after($str,'&lt;')"/> 
    <xsl:variable name="fulltag" select="fn:substring-before($rest,'&gt;')"/> 
    <xsl:variable name="tagparts" select="fn:tokenize($fulltag,'[ &#xA;]')"/> 
    <xsl:variable name="tag" select="$tagparts[1]"/> 
    <xsl:variable name="aftertag" select="fn:substring-after($rest,'&gt;')"/> 
    <xsl:variable name="intag" select="fn:substring-before($aftertag,fn:concat(fn:concat('&lt;/',$tag),'&gt;'))"/> 
    <xsl:variable name="afterall" select="fn:substring-after($aftertag,fn:concat(fn:concat('&lt;/',$tag),'&gt;'))"/> 
    <xsl:value-of select="$start"/> 
    <xsl:choose> 
    <xsl:when test="$tag"> 
     <xsl:variable name="currtag" select="$allowedtags/*[$tag = local-name()]"/> 
     <xsl:if test="$currtag"> 
      <xsl:element name="{$currtag/local-name()}"> 
       <xsl:for-each select="$tagparts[position()>1]"> 
        <xsl:variable name="anstring" select="fn:replace(.,'^([^ &#xA;=]*)=.*$','$1')"/> 
        <xsl:variable name="antag" select="$currtag/*[$anstring = local-name()]"/> 
        <xsl:if test="$antag"> 
         <xsl:attribute name="{$antag/local-name()}"> 
          <xsl:value-of select="fn:replace(.,'^.*[^ &#34;]*&#34;([^&#34;]*)&#34;.*','$1')"/> 
         </xsl:attribute> 
        </xsl:if> 
       </xsl:for-each> 
       <xsl:if test="$intag"> 
        <xsl:call-template name="doc"> 
         <xsl:with-param name="str"> 
          <xsl:value-of select="$intag"/> 
         </xsl:with-param> 
        </xsl:call-template> 
       </xsl:if> 
      </xsl:element> 
     </xsl:if> 
     <xsl:if test="$afterall"> 
      <xsl:call-template name="doc"> 
       <xsl:with-param name="str"> 
        <xsl:value-of select="$afterall"/> 
       </xsl:with-param> 
      </xsl:call-template> 
     </xsl:if> 
    </xsl:when> 
    <xsl:otherwise> 
        <xsl:value-of select="$str"/> 
    </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

</xsl:stylesheet> 
+0

'@ * | * | processing-instruction() | comment()' se puede acortar a '@ * | nodo() ' – Vampire