gpt4 book ai didi

c# - XML(反)序列化无效字符串在 C# 中不一致?

转载 作者:可可西里 更新时间:2023-11-01 08:04:28 25 4
gpt4 key购买 nike

在 C#(.net 4.0 和 4.5/vs2010 和 vs12)中,当我使用 XMLSerializer 序列化包含具有非法字符的字符串的对象时,不会抛出任何错误。但是,当我反序列化该结果时,会抛出“无效字符”错误。

        // add to XML
Items items = new Items();
items.Item = "\v hello world"; // contains "illegal" character \v

// variables
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Items));
string tmpFile = Path.GetTempFileName();

// serialize
using (FileStream tmpFileStream = new FileStream(tmpFile, FileMode.Open, FileAccess.ReadWrite))
{
serializer.Serialize(tmpFileStream, items);
}
Console.WriteLine("Success! XML serialized in file " + tmpFile);

// deserialize
Items result = null;
using (FileStream plainTextFile = new FileStream(tmpFile, FileMode.Open, FileAccess.Read))
{
result = (Items)serializer.Deserialize(plainTextFile); //FAILS here
}

Console.WriteLine(result.Item);

“Items”只是 xsd/c Items.xsd 自动生成的一个小类。 Items.xsd 只不过是包含一个子元素(Item)的根元素(Items):

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="Items">
<xs:complexType>
<xs:sequence>
<xs:element name="Item" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

反序列化时抛出的错误是

Unhandled Exception: System.InvalidOperationException: There is an error in XML document (3, 12). ---> System.Xml.XmlException: '♂', hexadecimal value 0x0B, is an invalid character. Line 3, position 12.

序列化的 XML 文件在第 3 行包含:

<Item>&#xB; hello world</Item>

我知道\v -> & # xB;是一个非法字符,但为什么 XMLSerialize 允许它被序列化(没有错误)?我发现它与 .NET 不一致,它允许我毫无问题地序列化某些东西,却发现我无法反序列化它。

是否有解决方案,使 XMLSerializer 在序列化之前自动删除非法字符,或者我可以指示反序列化忽略非法字符?

目前我确实通过读取文件内容作为字符串来解决它,“手动”替换非法字符然后反序列化它......但我发现这是一个丑陋的 hack/work around。

最佳答案

1.

您可以设置XmlWriterSettingsCheckCharacters属性来避免写入非法字符。(Serialize方法会抛出异常)

using (FileStream tmpFileStream = new FileStream(tmpFile, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var writer = XmlWriter.Create(tmpFileStream, new XmlWriterSettings() { CheckCharacters = true});
serializer.Serialize(writer, items);
}

2.

您可以创建自己的 XmlTextWriter 以在序列化时过滤掉不需要的字符

using (FileStream tmpFileStream = new FileStream(tmpFile, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
var writer = new MyXmlWriter(tmpFileStream);
serializer.Serialize(writer, items);
}

public class MyXmlWriter : XmlTextWriter
{
public MyXmlWriter(Stream s) : base(s, Encoding.UTF8)
{
}

public override void WriteString(string text)
{
string newText = String.Join("", text.Where(c => !char.IsControl(c)));
base.WriteString(newText);
}
}

3.

通过创建自己的 XmlTextReader,您可以在反序列化时过滤掉不需要的字符

using (FileStream plainTextFile = new FileStream(tmpFile, FileMode.Open, FileAccess.Read))
{
var reader = new MyXmlReader(plainTextFile);
result = (SomeObject)serializer.Deserialize(reader);
}

public class MyXmlReader : XmlTextReader
{
public MyXmlReader(Stream s) : base(s)
{
}

public override string ReadString()
{
string text = base.ReadString();
string newText = String.Join("", text.Where(c => !char.IsControl(c)));
return newText;
}
}

4.

您可以将 XmlReaderSettingsCheckCharacters 属性设置为 false。反序列化现在可以顺利进行。 (你会得到 \v 回来。)

using (FileStream plainTextFile = new FileStream(tmpFile, FileMode.Open, FileAccess.Read))
{
var reader = XmlReader.Create(plainTextFile, new XmlReaderSettings() { CheckCharacters = false });
result = (SomeObject)serializer.Deserialize(reader);
}

关于c# - XML(反)序列化无效字符串在 C# 中不一致?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13450117/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com