Странные символы в XML-файле (из пользовательского ввода?)
-
25-09-2019 - |
Вопрос
Эй, ребята, у меня есть приложение, которое сохраняет данные с помощью XML.Недавно я получил сообщение об ошибке от пользователя, который не может открыть свой файл данных.Анализатор, по-видимому, потерпел неудачу, когда столкнулся с плохим символом.
К счастью, у меня есть копия ее файла с данными, так что я смог найти преступника, но я не понимаю, что это такое и как оно туда попало.(Поскольку это все ввод с клавиатуры пользователем.) Недопустимыми символами являются:
attributeName="Some text then XXX"
Где находится "XXX", согласно шестнадцатеричному редактору:
0A 0A 00
0A - это перевод строки, насколько я могу судить, но как, черт возьми, там окажется нулевой символ?!Это первая ошибка, которую я увидел подобного рода.
Решение
Я думаю, проблема, которую вы видите, является малоизвестным, но очень серьезным недостатком 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);
}
}