C# Unicode到Windows-1251的XML(HTML)转换-转义

C# Unicode到Windows-1251的XML(HTML)转换-转义,c#,html,xml,encoding,xslt,C#,Html,Xml,Encoding,Xslt,我有XML文件,需要通过应用XSL转换生成带有Windows-1251编码的HTML文件。一个问题是XSL-file的Unicode字符没有像“ғ;”那样转换为HTML Unicode转义序列,在XSL转换过程中,只写入“?”符号而不是它们。如何要求XslCompiledTransform.Transform方法进行此转换?或者是否有任何方法可以通过应用HTML Unicode转义序列将HTML字符串写入Windows-1251 HTML文件,以便我可以对字符串执行XSL转换,然后通过

我有XML文件,需要通过应用XSL转换生成带有Windows-1251编码的HTML文件。一个问题是XSL-file的Unicode字符没有像“ғ;”那样转换为HTML Unicode转义序列,在XSL转换过程中,只写入“?”符号而不是它们。如何要求XslCompiledTransform.Transform方法进行此转换?或者是否有任何方法可以通过应用HTML Unicode转义序列将HTML字符串写入Windows-1251 HTML文件,以便我可以对字符串执行XSL转换,然后通过此方法使用Windows-1251编码和所有Unicode字符的HTML转义写入文件(类似Convert(“ғ”)的内容将返回“ғ;”)


我目前的解决方案是将大于127(c>127)的所有字符转换为&#dddd;转义字符串,但我的主管对解决方案不满意,因为生成的HTML文件的源代码不可读。

尝试使用替换规则来补充xsl文件

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

您可能希望改为使用正则表达式模式执行此操作:

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

您的问题源于xml解析器,该解析器在转换发生之前将数字实体引用替换为相应的unicode字符。因此,未知字符(resp.“?”) 在转换后的文档中结束

希望这有帮助

致以最良好的祝愿

carsten正确的解决方案是使用Unicode编码(如UTF-8)编写文件,而忽略CP-1251和所有其他传统编码

但我认为出于某种原因,这不是一个选择

我能想出的最佳替代方法是在将字符串交给XmlReader之前替换字符串中的字符。您应该使用Encoding类将字符串转换为CP-1251中的字节数组,并创建自己的解码器回退机制。然后,回退机制可以插入XML转义序列。这样,您就可以保证处理CP-1251中未包含的所有字符(以及那些字符)

然后,您可以将字节数组(在CP-1251中)转换为普通的.NET字符串(在UTF-16中),并将其交给XmlReader。需要转义的值将已经转义,因此应正确写入最终文件

更新

我刚刚意识到这种方法的缺陷。XmlWriter将进一步将&characters转义为
&,因此转义符本身将出现在最终文档中,而不是它们所表示的字符中

这可能需要一些非常复杂的解决方案

另一次更新

忽略上次的更新。因为您是以XML的形式读取字符串,所以转义应该被正确解释。这就是我快速尝试帖子而不是思考问题所得到的


我建议的解决方案应该可以正常工作。

您是否尝试过在xsl:output中指定编码?
()

请注意,XML既是一种数据模型,也是一种序列化格式。数据可以使用与此数据的序列化不同的字符集

看起来问题的关键原因是序列化过程试图限制数据模型的字符集,而您希望设置序列化格式的字符集。让我们举个例子:
Motörhead
Motö;rhead
是相等的XML文档。它们具有相同的结构和完全相同的数据。由于数据的字符集是unicode(或大于ASCII的字符集),但由于字符引用的使用
和#246,文档的后一种序列化形式的字符集为ASCII。为了处理这些数据,您的XML工具在这两种情况下仍然需要支持unicode,但在使用后一种序列化时,I/O和文件传输工具不需要支持unicode

我的猜测是,通过告诉
XMLTextWriter
使用Windows-1251编码,它实际上可能试图通过丢弃此字符集之外的所有字符并编写
字符,将数据的字符集限制为Windows-1251中包含的字符

然而,由于您通过XSL转换生成XML文档,所以可以直接在XSLT文档中控制序列化的字符集。这是通过向xsl:output元素添加编码属性来完成的。将其修改为如下所示

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

现在XSLT处理器负责简化字符集的序列化,并为windows-1251中包含的数据中的所有字符输出字符引用


如果您确实需要更改数据的字符集,那么您需要使用合适的字符转换库来处理数据,该库可以猜测最合适的替换字符(如
o
->
o
)。

最安全、最可互操作的方法是指定encoding=“us ascii”在xsl:output元素中。大多数XSLT处理器都支持编写这种编码

US-ASCII是一种完全安全的编码,因为它是UTF-8的兼容子集(您可以选择将发出的XML标记为具有“UTF-8”编码,因为这也是正确的:这可以通过为xsl:output指定omit XML declaration=“yes”并手动在输出前添加一个“声明”来实现)

这种方法之所以有效,是因为在使用US-ASCII编码时,序列化程序被迫对U+007F以外的字符使用XML的转义机制,因此会将它们作为数字字符引用(即“&#…”形式)发出

在处理需要非标准编码的环境时,生成这种XML通常是一种很好的防御技术,因为它是完全一致的,在实践中甚至会产生一些错误
<xsl:value-of select="replace(.,'&#1171;','&amp;#1171;')"/>
<xsl:value-of select="replace(.,'&#(\d+);','&amp;#$1;')"/>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/>