xslt总是给我带斜线的UTF-16

时间:2017-07-26 11:53:35

标签: c# .net xml xslt utf-8

我在C#中有以下一些代码,用于使用XSLT /

将XML文件转换为另一个
string xmlInput = @"<?xml version='1.0' encoding='UTF-8'?><catalog><cd><title> Empire Burlesque </title ><artist> Bob Dylan </artist><country> USA </country><company> Columbia </company><price> 10.90 </price><year> 1985 </year></cd></catalog>";

            ///////////////////////////////////////////////////////////////
            string xmlOutput = String.Empty;            
            using (StringReader sri = new StringReader(xmlInput))
            {
                using (XmlReader xri = XmlReader.Create(sri))                
                {
                    XslCompiledTransform xslt = new XslCompiledTransform();
                    //xslt.Load(xrt);
                    xslt.Load(@"XSLT/slide2.xslt");
                    using (StringWriter sw = new StringWriter())
                    using (XmlWriter xwo = XmlWriter.Create(sw, new XmlWriterSettings { Encoding = Encoding.UTF8 }))
                    {
                        xslt.Transform(xri, xwo);

                        xmlOutput = sw.ToString();
                    }
                }
            }

xmlOutput给了我"<?xml version=\"1.0\" encoding=\"utf-16\"?><root> Empire Burlesque </root>" 我怎么能得到utf-8而没有斜线?

4 个答案:

答案 0 :(得分:0)

.NET字符串是UTF-16编码字符的序列,StringWriter / StringBuilder默认为该编码。 (来源https://forums.asp.net/post/3240311.aspx

所以你需要创建一个继承默认字符串编写器的类:

public class StringWriterWithEncoding : StringWriter
{
    Encoding myEncoding;

    public override Encoding Encoding
    {
        get
        {
            return myEncoding;
        }
    }

    public StringWriterWithEncoding(Encoding encoding) : base()
    {
        myEncoding = encoding;
    }

    public StringWriterWithEncoding(Encoding encoding) : base(CultureInfo.CurrentCulture)
    {
        myEncoding = encoding;
    }

    public StringWriterWithEncoding(StringBuilder sb, Encoding encoding) : base(sb, CultureInfo.CurrentCulture)
    {
        myEncoding = encoding;
    }
}

并创建一个实例,例如StringWriterWithEncoding utf8Writer = new StringWriterWithEncoding(Encoding.UTF8);并将其作为XslCompiledTransform的Transform方法的第三个参数传递。

像这样使用:

StringBuilder sb = new StringBuilder();
using (StringWriterWithEncoding sw = new StringWriterWithEncoding(sb, Encoding.UTF8))
{
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load(@"XSLT/slide2.xslt");
    xslt.Transform(xri, sw);
}
xmlOutput = sb.ToString();

答案 1 :(得分:0)

第一个问题是由StringWriter

引起的
using (StringWriter sw = new StringWriter())
using (XmlWriter xwo = XmlWriter.Create(sw, new XmlWriterSettings { Encoding = Encoding.UTF8 }))

即使您专门将XmlWriterSettings.Encoding设置为UTF-8,也要将输出流指定为StringWriter,并且由于.NET字符串为UTF-16,因此XmlWriter必须使用UTF-16。 如果您使用例如FileStream而不是StringWriter,则输出将采用UTF-8或您指定的任何编码。

斜杠问题只是你的IDE逃避它。如果您将xmlOutput打印到Console,您将看到它不包含额外的斜杠。

答案 2 :(得分:0)

您可以在XSLT样式表中包含此行:

<xsl:output encoding="utf-8"/>

(或者当然是您喜欢的编码),它会自动将输出设置设置为utf-8编码。

答案 3 :(得分:0)

我相信使用MemoryStream是处理此问题的更好方法。 .net字符串在内部是utf-16,这是在您写入StringBuilder对象的StringWriter时对它们进行编码的方式。使用内存流,可以避免这种陷阱。

string xmlDoc = "";

// Use a memory stream to avoid the .net internal string utf-16 encoding pitfall.
using (MemoryStream xmlStream = new MemoryStream())
using (XmlReader xmlReader = XmlReader.Create(new StringReader(xmlAsText)))
using (XmlReader xsltReader = XmlReader.Create(new StringReader(xsltAsText)))
{
    // Transform XML string to new XML based on the XSLT
    // Load the XSLT and transform source XML to target XML
    XslCompiledTransform myXslTrans = new XslCompiledTransform();
    myXslTrans.Load(xsltReader);
    myXslTrans.Transform(xmlReader, null, xmlStream);

    // Using the encoding from the xslt, transform the xml stream bytes to the xml string.
    // If no encoding in xslt, defaults to UTF-8.
    xmlDoc = myXslTrans.OutputSettings.Encoding.GetString(xmlStream.ToArray());

    // Remove the BOM if it exists
    string byteOrderMark = myXslTrans.OutputSettings.Encoding.GetString(myXslTrans.OutputSettings.Encoding.GetPreamble());
    if (xmlDoc.StartsWith(byteOrderMark, StringComparison.Ordinal))
    {
        xmlDoc = xmlDoc.Remove(0, byteOrderMark.Length);
    }
}

如果样式表中没有编码属性,则默认情况下您将获得UTF-8,而不是UTF-16。这与将其直接写入文件一样。抱歉,我无法说说它如何在不同的文化中发挥作用。

我建议使用这种方法,而不要使用其他方法对UTF-8进行硬编码。可以使用样式表中的任何(有效)编码,例如ISO-8859-1。