Странные символы в XML-файле (из пользовательского ввода?) - PullRequest
1 голос
/ 06 января 2011

Эй, ребята, у меня есть приложение, которое сохраняет данные с использованием XML. Недавно я получил сообщение об ошибке от пользователя, который не может открыть ее файл данных. Синтаксический анализатор, по-видимому, потерпел неудачу, когда обнаружил плохой символ.

К счастью, у меня есть копия ее файла данных, поэтому я смог найти виновника, но я не понимаю, что это такое и как оно туда попало. (Поскольку все это ввод с клавиатуры пользователем.) Оскорбительные символы:

attributeName="Some text then XXX"

Где находится "XXX", в соответствии с шестнадцатеричным редактором:

0A 0A 00

Насколько я могу судить, 0A - это перевод строки, но как, черт возьми, нулевой символ может оказаться там ?! Это первая ошибка, с которой я столкнулся.

1 Ответ

2 голосов
/ 06 января 2011

Я думаю, что проблема, которую вы видите, является малоизвестной, но очень серьезной ошибкой в ​​XML.В двух словах: значения xml не могут содержать определенные символы, и они не только не могут быть в тексте xml, но даже не могут быть экранированы с помощью & # DDDD;нотация.

Здесь можно найти действительную кодировку XML: http://www.w3.org/TR/REC-xml/#charsets, и это: # x9 |#xA |#xD |[# x20- # xD7FF] |[# xE000- # xFFFD] |[# x10000- # x10FFFF].

Это означает, что если в вашей строке есть какой-либо символ, не включенный в этот набор символов, она не может быть преобразована в значение XML.Единственный способ сохранить такую ​​строку - это сериализовать ее в base64 в виде двоичных данных.

Многие популярные платформы, включая MSXML и .NET, позволяют помещать неверные данные в значения XML, а затем отказываются десериализовать такой XML.,Вот пример, скриншот: http://vvcap.net/db/Db94W-13uwCkNXSZTitO.htp, и исходный код:

using System;
using System.Xml.Serialization;
using System.Xml;

[Serializable] public class TestClass
{
    [XmlAttribute]
    public string Member { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var ser = new XmlSerializer(typeof(TestClass));
        var tc = new TestClass() { Member = "zzz \x19 zzz" };
        var stream = new System.IO.StringWriter();
        ser.Serialize(stream, tc);
        var xml = stream.ToString();
        var stream2 = new System.IO.StringReader(stream.ToString());
        var tc2 = ser.Deserialize(stream2);
    }
}
...