Xml сериализация в .Net Framework 2.0
Страница 2. Namespce и сериализация


 

Namespce и сериализация

Когда мы используем для сериализации метод XmlUtility.Obj2XmlStr(obj), мы можем заметить, что результирующий xml получается несколько более компактным чем прежде потому, что из него исчезли стандартные префиксы нэймспейсов XmlSchema - xsd и XmlSchema Instance - xsi :
<?xml version="1.0" encoding="utf-8"?>
<Data ID="078ce191-f781-4052-93fd-766309c2abaa" Name="Just Name">
<Reserved>10</Reserved>
</Data>
Произошло это из-за использования перегруженного метода SmlSerializer.Serialize(), в котором явно указывается перечень используемых Xml namespace – ов (пустой в данном конкретном случае).

Есть в нашей утилите и метод, позволяющий явно задать namespace для сериализации - Obj2XmlStr(object obj, string nameSpace). Учет Xml namespace при сериализации очень важен. Рассмотрим следующий пример:
DataClass obj = new DataClass();
// зададим явно XmlNamespace при сериализации

string xml = XmlUtility.Obj2XmlStr(obj, "urn:MyDataClass");
Console.WriteLine(xml);
DataClass clone = XmlUtility.XmlStr2Obj<DataClass>(xml);
При попытке десериализации полученного Xml обратно в объект, в пятой строке мы получим исключение:
<?xml version="1.0" encoding="utf-8"?>
<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.
Дело в том, что сериалайзеру не было никаких указаний по поводу Xml namespace для данного класса. И появление объявления namespace по умолчанию xmlns="urn:MyDataClass" становится непреодолимой преградой на пути десериализации Xml в объект. Явно указать, какой namespace надо использовать сериалайзеру можно в атрибуте XmlRootAttribute. Например:
 [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. Поэтому данному вопросу необходимо постоянно уделять внимание.

 
Следующая статья »