visor - XML to WordML using XSLT 1.0-reemplace las etiquetas html dentro del contenido xml con etiquetas de formato wordML
xslt editor (4)
Estoy creando un documento de WordML a partir de un archivo xml cuyos elementos a veces contienen texto con formato html.
<w:p>
<w:r>
<w:t> html formatted content is in here taken from xml file! </w:t>
</w:r>
</w:p>
Así es como mis plantillas están configuradas. Tengo una función de plantilla de llamada recursiva que reemplaza el texto con el contenido xml fuente. Cuando aparece una etiqueta " <b>
", obtengo una cadena en CDATA que contiene " </w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>
"para cerrar la ejecución actual y comenzar una nueva ejecución con el formato en negrita habilitado. cuando llega a una etiqueta " </b>
", la reemplaza con la siguiente cadena de CDATA " </w:t></w:r><w:r><w:t>
".
Lo que me gustaría hacer es usar XSL para cerrar la etiqueta de ejecución y comenzar una nueva ejecución sin usar inserciones de cadena de CDATA. es posible?
Para terminar completamente el HTML> WordML, recomiendo esta versión editada de tu código:
<xsl:template match="Body"><xsl:apply-templates select="p"/></xsl:template>
<xsl:template match="text()" priority="1"><w:r><w:t><xsl:value-of select="."/></w:t></w:r></xsl:template>
<xsl:template match="@*|node()"><xsl:apply-templates select="@*|node()"/></xsl:template>
<xsl:template match="p"><w:p><xsl:apply-templates select="text() | *" /></w:p></xsl:template>
<xsl:template match="b"><w:r><w:rPr><w:b /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
<xsl:template match="i"><w:r><w:rPr><w:i /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
<xsl:template match="u"><w:r><w:rPr><w:u w:val="single" /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
suponiendo que tiene su HTML en algún lugar de un XMl envuelto en una etiqueta
Probablemente pueda ayudarlo si solo entendiera su problema ... ¿Está el html en una sección CDATA o se analiza como parte del documento de entrada (y, por lo tanto, XML bien formado)? Como hablas de ''reemplazo de texto'', asumiré que tratas el ''contenido formateado en html'' como una cadena única (CDATA) y por lo tanto necesitas una función de plantilla de llamada recursiva para realizar el reemplazo de cadena. La única forma en que podrá usar una plantilla de coincidencia XSL para hacer lo que está haciendo ahora es convertir la parte html del documento analizado (su documento de entrada). En tal caso, podría simplemente hacer coincidir la etiqueta b
y reemplazarla con la salida apropiada (nuevamente: esto supone que siempre se puede analizar como XML válido). Tu problema ahora ha cambiado ... ya que (si entendí tu problema correctamente) lo que estás tratando de hacer es cerrar los elementos w:t
y w:r
y luego ''reabrirlos'' ... esto es difícil porque es ( como probablemente sospeche) es muy difícil hacerlo bien en XSLT (no puede simplemente crear un elemento en la plantilla A y luego cerrarlo en la plantilla B). Tendrás que empezar a jugar con la salida sin escalar, etc. para que esto suceda. Ahora he hecho muchas suposiciones, pero aquí hay un pequeño ejemplo para ayudarte en tu camino:
input.xml
<doc xmlns:w="urn:schemas-microsoft-com:office:word">
<w:p>
<w:r>
<w:t>before<b>bold</b>after</w:t>
</w:r>
</w:p>
</doc>
convert_html.xsl
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/doc/w:p/w:r/w:t//b">
<xsl:value-of select="''</w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>''" disable-output-escaping="yes" />
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="''</w:t></w:r><w:r><w:t>''" disable-output-escaping="yes" />
</xsl:template>
Ahora corriendo
xalan input.xml convert_html.xsl
produce
<?xml version="1.0" encoding="UTF-8"?><doc xmlns:w="urn:schemas-microsoft-com:office:word">
<w:p>
<w:r>
<w:t>before</w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>bold</w:t></w:r><w:r><w:t>after</w:t>
</w:r>
</w:p>
</doc>
que supongo que es lo que querías
Espero que esto te ayude un poco.
Según su descripción, parece que puede analizar el html incrustado. Si es así, simplemente aplicando plantillas debería hacer lo que quiera. El wordML en la salida puede no ser correcto, pero con suerte esto ayudará.
Muestra de entrada:
<text>
<para>
Test for paragraph 1
</para>
<para>
Test for <b>paragraph 2</b>
</para>
</text>
Transformar:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://foo">
<xsl:template match="/">
<w:p>
<w:r>
<xsl:apply-templates/>
</w:r>
</w:p>
</xsl:template>
<xsl:template match="para">
<w:t>
<xsl:apply-templates/>
</w:t>
</xsl:template>
<xsl:template match="b">
<w:rPr>
<w:b/>
</w:rPr>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Resultado:
<w:p xmlns:w="http://foo">
<w:r>
<w:t>
Test for paragraph 1
</w:t>
<w:t>
Test for <w:rPr><w:b /></w:rPr>paragraph 2
</w:t>
</w:r>
</w:p>
Trabajar con WordML es complicado. Un consejo al convertir XML arbitrario en WordML con XSLT es no preocuparse por el texto que se ejecuta al procesar bloques, sino crear una plantilla que coincida directamente con los nodos de texto () y crear el texto que se ejecuta allí. Resulta que a Word no le importa si anida el texto, lo que hace que el problema sea mucho más fácil de resolver.
<xsl:template match="text()" priority="1">
<w:r>
<w:t>
<xsl:value-of select="."/>
</w:t>
</w:r>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="para">
<w:p>
<xsl:apply-templates select="text() | *" />
</w:p>
</xsl:template>
<xsl:template match="b">
<w:r>
<w:rPr>
<w:b />
</w:rPr>
<w:t><xsl:apply-templates /></w:t>
</w:r>
</xsl:template>
Esto evita la mala técnica XSLT de insertar etiquetas directamente como texto escapado. Terminará con la etiqueta en negrita como ejecución de texto anidado, pero como dije, Word no podría importarle menos. Si usa esta técnica, deberá tener cuidado de no aplicar plantillas al espacio vacío entre párrafos, ya que activará la plantilla de texto y creará una ejecución fuera de contexto.