Xml сериализация в .Net Framework 2.0 - Namespce и сериализация
ОГЛАВЛЕНИЕ
Namespce и сериализация
Когда мы используем для сериализации метод XmlUtility.Obj2XmlStr(obj), мы можем заметить, что результирующий xml получается несколько более компактным чем прежде потому, что из него исчезли стандартные префиксы нэймспейсов XmlSchema - xsd и XmlSchema Instance - xsi :<?xml version="1.0" encoding="utf-8"?>Произошло это из-за использования перегруженного метода SmlSerializer.Serialize(), в котором явно указывается перечень используемых Xml namespace – ов (пустой в данном конкретном случае).
<Data ID="078ce191-f781-4052-93fd-766309c2abaa" Name="Just Name">
<Reserved>10</Reserved>
</Data>
Есть в нашей утилите и метод, позволяющий явно задать namespace для сериализации - Obj2XmlStr(object obj, string nameSpace). Учет Xml namespace при сериализации очень важен. Рассмотрим следующий пример:
DataClass obj = new DataClass();При попытке десериализации полученного Xml обратно в объект, в пятой строке мы получим исключение:
// зададим явно XmlNamespace при сериализации
string xml = XmlUtility.Obj2XmlStr(obj, "urn:MyDataClass");
Console.WriteLine(xml);
DataClass clone = XmlUtility.XmlStr2Obj<DataClass>(xml);
<?xml version="1.0" encoding="utf-8"?>Дело в том, что сериалайзеру не было никаких указаний по поводу Xml namespace для данного класса. И появление объявления namespace по умолчанию xmlns="urn:MyDataClass" становится непреодолимой преградой на пути десериализации Xml в объект. Явно указать, какой namespace надо использовать сериалайзеру можно в атрибуте XmlRootAttribute. Например:
<Data xmlns="urn:MyDataClass" ID="e46917f4-691a-4a7f-9f0b-d9be5e018a1f" Name="Just Name">
<Reserved>10</Reserved>
</Data>
System.InvalidOperationException : <Data xmlns='urn:MyDataClass'> was not expected.
[XmlRoot("Data", Namespace=DataClass.XmlNamespace )]После этих изменений в коде, ошибка времени выполнения при десериализации пропадает и код, приведенный ранее, выполняется.
public class DataClass
{
public const string XmlNamespace = "urn:MyDataClass";
А что будет, если теперь при сериализации не указывать namespace явно, а вызвать
string xml = XmlUtility.Obj2XmlStr(obj);Результирующий Xml опять изменится, но сериализация и десериализация выполнятся без ошибок:
<?xml version="1.0" encoding="utf-8"?>
<q1:Data ID="1458c25e-4356-4df5-b918-a44c9bf5e4b0" Name="Just Name" xmlns:q1="urn:MyDataClass">
<q1:Reserved>10</q1:Reserved>
</q1:Data>
Мы видим, что все xml элементы получили префикс “ql”. Произошло это из-за того, что namespace "urn:MyDataClass" объявлен в атрибуте XmlRoot нашего класса, а при сериализации он не был задан в качестве namespace по умолчанию. Таких ситуаций следует избегать. Лучше, либо вообще не использовать namespace, либо задавать их явно в качестве namespace по умолчанию, что позволяет избежать использования префиксов в Xml. Nmespace можно задать не только для класса, но и для каждого элемента в отдельности (но без нужды лучше этого не делать). Кроме того, при разработке крупных систем, может оказаться, что для разных классов заданы разные namespace, и тут уже не избежать появления префиксов имен в результирующем Xml. Поэтому данному вопросу необходимо постоянно уделять внимание.