Недопустимая строка сериализации XML (de)несовместима в c#?
В 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);
"элементы" - это всего лишь небольшой класс, автогенерируемый элементами xsd /C.XSD-файл. Предметы.xsd - это не более чем корневой элемент (элементы), содержащий один дочерний элемент (элемент):
<?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>
ошибка при десериализации is
Необработанное Исключение: Система.InvalidOperationException: существует ошибка в XML-документе (3, 12). ---> Система.XML.Xmlexception в: '♂', шестнадцатеричное значение 0x0B, является недопустимым знаком. Линия 3, позиция 12.
сериализованный XML-файл содержит в строке 3 это:
<Item> hello world</Item>
Я знаю, что v - > & # xB; является незаконным символом, но почему XMLSerialize позволяет сериализовать его (без ошибок)? Я считаю непоследовательным .NET, что это позволяет мне сериализовать что-то без проблем, только чтобы узнать, что я не могу десериализовать его.
есть ли решение, чтобы XMLSerializer автоматически удалял незаконные символы перед сериализацией или я мог поручить десериализации игнорировать незаконные символы?
В настоящее время я решаю его, читая содержимое файла в виде строки, заменяя "вручную" незаконные символы и затем десериализуя его... но я считаю, что уродливый Хак / работа вокруг.
1 ответов
1.
вы можете установить XmlWriterSettings
' s CheckCharacters
свойство, чтобы избежать написания незаконных символов.(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.
вы можете установить XmlReaderSettings
' s CheckCharacters
свойство 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);
}