2011-05-10 27 views
8

Tengo un archivo XML y necesito producir un archivo HTML con codificación Windows-1251 aplicando XSL Transformation. Un problema es que los caracteres Unicode de XSL -file no se convierten a HTML Unicode Escape Sequence como "& # 1171;" durante la Transformación XSL, solo "?" signo está escrito en lugar de ellos. ¿Cómo puedo solicitar el método XslCompiledTransform.Transform para hacer esta conversión? ¿O hay algún método para escribir HTML-string en el archivo HTML de Windows-1251 con la aplicación de HTML Unicode Escape Sequences, de modo que pueda realizar Transformación XSL en cadena y luego mediante este método escribir en un archivo con codificación Windows-1251 y con HTML -escapar todos los caracteres Unicode (algo así como Convertir ("ғ") devolverá "& # 1171;")?Unicode a Windows-1251 Conversión con XML (HTML) -escaping

XmlReader xmlReader = XmlReader.Create(new StringReader("<Data><Name>The Wizard of Wishaw</Name></data>")); 

XslCompiledTransform xslTrans = new XslCompiledTransform(); 
xslTrans.Load("sheet.xsl"); 

using (XmlTextWriter xmlWriter = new XmlTextWriter("result.html", Encoding.GetEncoding("Windows-1251"))) 
{ 
    xslTrans.Transform(xmlReader, xmlWriter); // it writes Windows-1251 HTML-file but does not escape unicode characters, just writes "?" signs 
} 

¡Gracias a todos por su ayuda!

ACTUALIZACIÓN

Mi etiqueta de configuración de salida de archivo XSL-:

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" /> 

ni siquiera me esperan ahora que XSL va a satisfacer mis necesidades. Pero me pregunto si no tengo ningún método para verificar si el carácter es aceptable por la codificación especificada. Algo así como

Char.IsEncodable('ғ', Encoding.GetEncoding('Windows-1251')) 

Mi solución actual es convertir todos los caracteres mayor que 127 (c> 127) a & #dddd; cadenas de escape, pero mi jefe no está satisfecho con la solución, porque la fuente del archivo HTML generado no es legible.

+2

Espero que eventualmente pueda deshacerse de la necesidad de CP-1251 en cualquier sistema con el que esté trabajando. ¡Las codificaciones que no sean Unicode deberían considerarse un truco temporal en el mejor de los casos! –

+0

¿Podría publicar sus primeras líneas en el archivo de la hoja de estilo? Me parece que vale la pena evaluar el elemento xsl: output en este punto. – Osiris76

+0

¿Intentó especificar el atributo de codificación en el elemento ? Normalmente trabajo con UTF-8 en estas ocasiones, pero podrías intentar insertar 'Windows-1251' en su lugar. – Osiris76

Respuesta

0

oportunidad para complementar su XSL-archivo con el reemplazo gobierna a la

<xsl:value-of select="replace(.,'&#1171;','&amp;#1171;')"/> 

es posible que desee hacer esto utilizando patrones de expresiones regulares en su lugar:

<xsl:value-of select="replace(.,'&#(\d+);','&amp;#$1;')"/> 

sus orígenes de problemas con el analizador XML que sustituye la referencia de entidad numérica con los caracteres Unicode correspondientes antes de que tenga lugar la transformación. por lo tanto, los caracteres desconocidos (resp. '?') terminan en su documento convertido.

esperanza que esta ayuda,

mejores deseos,

Carsten

0

La solución correctasería escribir el archivo en una codificación Unicode (como UTF-8) y olvidarse de CP -1251 y todas las demás codificaciones heredadas.

Pero supongo que esta no es una opción por alguna razón.

La mejor alternativa que puedo idear es hacer los reemplazos de caracteres en la cadena antes de pasarlos al XmlReader. Debería usar la clase de Codificación para convertir la cadena a una matriz de bytes en CP-1251, y crear su propio mecanismo de repliegue del decodificador. El mecanismo de reserva puede insertar las secuencias de escape XML. De esta forma, se le garantiza manejar todos (y exactamente esos) caracteres que no están en CP-1251.

Luego puede convertir la matriz de bytes (en CP-1251) en una .NET String normal (en UTF-16) y entregarla a su XmlReader. Los valores que deben escaparse ya se escaparon, por lo que el archivo final debe escribirse correctamente.

ACTUALIZACIÓN

me he dado cuenta de la falla de este método. El XmlWriter escapará aún más los caracteres & como &amp;, por lo que los escapes mismos aparecerán en el documento final en lugar de los caracteres que representan.

¡Esto puede requerir una solución muy complicada!

otra actualización

ignorar que la última actualización. Como está leyendo la cadena como XML, los escapes deben interpretarse correctamente. ¡Esto es lo que obtengo por intentar publicar rápidamente en lugar de pensar en el problema!

Mi solución propuesta debería funcionar bien.

1

Tenga en cuenta que XML es a la vez un modelo de datos y un formato de serialización. Los datos pueden usar un juego de caracteres diferente a la serialización de estos datos.

Parece que la razón principal de su problema es que su proceso de serialización está tratando de limitar el conjunto de caracteres del modelo de datos, mientras que le gustaría establecer el juego de caracteres del formato de serialización. Veamos un ejemplo: <band>Motörhead</band> y <band>Mot&#246;rhead</band> son documentos XML iguales. Tienen la misma estructura y exactamente los mismos datos. Debido a heavy metal umlaut, el juego de caracteres de los datos es unicode (o algo más grande que ASCII) pero, debido al uso de un carácter de referencia &#246;, el juego de caracteres de la última forma de serialización del documento es ASCII. Para procesar estos datos, sus herramientas XML aún deben tener conocimiento unicode en ambos casos, pero al usar la última serialización, las herramientas de E/S y transferencia de archivos no necesitan ser unicode.

Mi conjetura es que al contar la XMLTextWriter utilizar la codificación de Windows-1251, es probable que en la práctica, trata de limitar el juego de caracteres de los datos a los caracteres contenidos en Windows-1251, descartando todos los caracteres fuera de este personaje establecer y escribir un carácter ? en su lugar.

Sin embargo, dado que produce su documento XML mediante una transformación XSL, puede controlar el conjunto de caracteres de la serialización directamente en su documento XSLT. Esto se hace agregando un atributo de codificación al elemento xsl: output. Modificarlo para tener este aspecto

<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/> 

Ahora el procesador XSLT se encarga de la serialización de carácter conjunto reducido y da salida a una referencia de carácter para todos los caracteres en los datos que se incluyen en Windows-1251.

Si cambiar el conjunto de caracteres de los datos es realmente lo que necesita, debe procesar sus datos con una biblioteca de conversión de caracteres adecuada que adivine el carácter de reemplazo más adecuado (como ö ->o).

0

La forma más segura e interoperable de hacerlo es especificar encoding = "us-ascii" en su elemento xsl: output. La mayoría de los procesadores XSLT admiten la escritura de esta codificación.

US-ASCII es una codificación completamente segura ya que es un subconjunto compatible de UTF-8 (puede elegir etiquetar el XML emitido como que tiene una codificación "utf-8", como también será cierto: esto puede se puede hacer especificando omit-xml-declaration = "yes" para su xsl: output y anteponiendo manualmente una declaración "<? xml version = '1.0' encoding = 'utf-8'?>" a su salida).

Este enfoque funciona porque al usar la codificación US-ASCII, un serializador se ve obligado a usar el mecanismo de escape de XML para caracteres más allá de U + 007F, y así los emitirá como referencias de caracteres numéricos (el "& # ..... ; "forma".

Cuando se trata de entornos en los que se requieren codificaciones no estándar, generalmente es una buena técnica de defensa para producir este tipo de XML, ya que es completamente compatible y funciona en la práctica incluso con algunos programas que consumen errores.