Недопустимая строка сериализации 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>&#xB; 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); 
}