这个让我莫名其妙。我需要向俄罗斯的网络服务发送一条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服务会拒绝请求。在最新的例子中,我试图发送一个带有"LEFT-to-RIGHT EMBEDING"(U+202A)、"NON-BREAKING HYPHEN"(U+2011)和"POP DIRECTIONAL FORMATING"(U/202C)的电话号码。我无法控制输入。我想把任何未知的角色变成?或将其移除。我试过扰乱EncoderFallback,但它似乎没有改变任何事情。
我做错了吗?
由于您正在序列化为string
,Windows1251StringWriter
中的Encoding
属性唯一能为您做的就是更改XML:中显示的编码名称
<?xml version="1.0" encoding="windows-1251"?>
(我认为这个技巧来自这里。)
就是这样。所有的c#字符串总是在utf-16中编码,并且无论Encoding
属性是否被重写,基类StringWriter
都会写入这个编码。
要从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);