如何使用c#

时间:2016-05-04 09:20:21

标签: c# xml character-encoding

这个令我困惑的是没有尽头。我需要向俄语网络服务发送一条xml消息。 XML必须在windows-1251

中编码

我有许多对象可以响应不同类型的消息,因此我将它们转换为xml:

public string Serialise(Type t, object o, XmlSerializerNamespaces Namespaces)
{
    XmlSerializer serialiser = _serialisers.First(s => s.GetType().FullName.Contains(t.Name));
    Windows1251StringWriter myWriter = new Windows1251StringWriter();
    serialiser.Serialize(myWriter, o, Namespaces);
    return myWriter.ToString();
}

public class Windows1251StringWriter : StringWriter
{
    public override Encoding Encoding
    {
        get { return Encoding.GetEncoding(1251); }
    }
}

工作正常,但如果我们发送任何不在windows-1251中的字符,Web服务会拒绝请求。在最新的例子中,我尝试发送一个电话号码,其中包括“左至右嵌入”(U + 202A),“非爆炸性”(U + 2011)和上帝帮助我们“POP方向格式化”(U + 202C) )。我无法控制输入。我想把任何未知的角色变成?或删除它们。我试过搞乱EncoderFallback,但它似乎没有改变任何东西。

我是不是错了?

1 个答案:

答案 0 :(得分:2)

由于您要序列化为stringEncodingWindows1251StringWriter属性唯一能为您做的就是更改XML中显示的编码名称:

<?xml version="1.0" encoding="windows-1251"?>

(我认为这个技巧来自here。)

就是这样。所有c#字符串始终以utf-16编码,基类StringWriter无论如何都写入此编码,无论是否覆盖Encoding属性。

要从XML中删除某些特定编码中无效的字符,您需要将其编码为字节流,然后对其进行解码,例如:以下内容:

public static class XmlSerializationHelper
{
    public static string GetXml<X>(this X toSerialize, XmlSerializer serializer = null, XmlSerializerNamespaces namespaces = null, Encoding encoding = null)
    {
        if (toSerialize == null)
            throw new ArgumentNullException();
        encoding = encoding ?? Encoding.UTF8;
        serializer = serializer ?? new XmlSerializer(toSerialize.GetType());

        using (var stream = new MemoryStream())
        using (var writer = new StreamWriter(stream, encoding))
        {
            serializer.Serialize(writer, toSerialize, namespaces);
            writer.Flush();
            stream.Position = 0;
            using (var reader = new StreamReader(stream, encoding))
            {
                return reader.ReadToEnd();
            }
        }
    }
}

然后做

var encoding = Encoding.GetEncoding(1251, new EncoderReplacementFallback(""), new DecoderExceptionFallback());
return o.GetXml(serialiser, Namespaces, encoding);