C# Unicode到Windows-1251的XML(HTML)转换-转义
我有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(“ғ”)的内容将返回“ғ;”)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转换,然后通过
我目前的解决方案是将大于127(c>127)的所有字符转换为dddd;转义字符串,但我的主管对解决方案不满意,因为生成的HTML文件的源代码不可读。尝试使用替换规则来补充xsl文件
<xsl:value-of select="replace(.,'ғ','&#1171;')"/>
您可能希望改为使用正则表达式模式执行此操作:
<xsl:value-of select="replace(.,'&#(\d+);','&#$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;')"/>
<xsl:value-of select="replace(.,'&#(\d+);','&#$1;')"/>
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes" encoding="windows-1251"/>