Задача — десериализовать объект из xml без namespace. Для этого от XmlTextReader унаследовал класс, где подставляю нужный ns. Наткнулся на интересную вещь. Когда пытаюсь вытащить ns из атрибутов объекта, не работает — > System.InvalidOperationException: <Store xmlns='test.Serialization'> was not expected. Стоит заменить ns на константу все отлично работает. Причем в любом случае проверяется на равенство с константой.
environment: VS 2010, fw 3.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
namespace VertigoDataImport
{
static class TestSerializer
{
static XmlSerializer ser = new XmlSerializer(typeof(Store));
const string nsXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
"<Store xmlns=\"test.Serialization\">"+
" <Items Id=\"2011-09-20 09:02:37Z\" Name=\"name 1\" />"+
" <Items Id=\"2011-09-20 09:03:37Z\" Name=\"name 2\" />"+
"</Store>";
const string bareXml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<Store>" +
" <Items Id=\"2011-09-20 09:02:37Z\" Name=\"name 1\" />" +
" <Items Id=\"2011-09-20 09:03:37Z\" Name=\"name 2\" />" +
"</Store>";
static string GetXml(Store st)
{
StringBuilder sb = new StringBuilder();
using (var wr = XmlWriter.Create(sb))
{
ser.Serialize(wr, st);
wr.Close();
}
var xml = sb.ToString();
return xml;
}
static Store GenerateStore()
{
Store st = new Store
{
Items = new StoreItem[10]
};
for (int i = 0; i < 10; i++)
{
st.Items[i] = new StoreItem
{
Id = DateTime.Now.AddMinutes(i).ToString("u"),
Name = string.Format("name {0}", i + 1),
};
}
return st;
}
static Store DeserializeFromNSXml(string xml)
{
Store store = null;
StringReader sr = new StringReader(nsXml);
using (var rd = XmlReader.Create(sr))
{
store = (Store)ser.Deserialize(rd);
}
return store;
}
static Store DeserializeFromBareXml(string xml)
{
Store store = null;
try
{
using (var rd = new NamespaceXmlReader(typeof(Store), new StringReader(xml), true))
{
store = (Store)ser.Deserialize(rd);
}
Console.WriteLine("@@@ Succesfully deserialized using const ns");
}
catch (Exception e)
{
Console.WriteLine("*** Error while deserializing from bare xml using const ns.\n{0}", e.ToString());
}
try
{
using (var rd = new NamespaceXmlReader(typeof(Store), new StringReader(xml), false))
{
store = (Store)ser.Deserialize(rd);
}
Console.WriteLine("### Succesfully deserialized using extracted ns");
}
catch (Exception e)
{
Console.WriteLine("*** Error while deserializing from bare xml using extracted ns.\n{0}", e.ToString());
}
return store;
}
public static void Run()
{
Store store = DeserializeFromBareXml(bareXml);
if (store != null)
Console.WriteLine("deserialized. got {0} items", store.Items.Length);
else
Console.WriteLine("*** ERR: store is null");
Console.Write("Press any key to exit.. ");
Console.ReadKey();
}
}
[XmlRoot(Namespace="test.Serialization")]
[XmlType(Namespace="test.Serialization")]
public class Store
{
[XmlElement()]
public StoreItem[] Items { get; set; }
}
[XmlType(Namespace="test.Serialization")]
public class StoreItem
{
[XmlAttribute]
public string Id { get; set; }
[XmlAttribute]
public string Name { get; set; }
}
class NamespaceXmlReader : XmlTextReader
{
//const string _ns = "test.Serialization";
static string _ns = "test.Serialization";
string ns = "";
public NamespaceXmlReader(Type instanceType, System.IO.TextReader reader, bool useConst)
: base(reader)
{
if (useConst)
{
ns = _ns;
}
else
{
object[] attr_arr = instanceType.GetCustomAttributes(typeof(XmlTypeAttribute), false);
if (attr_arr.Length == 0)
Console.WriteLine("*** ERR: Attribute 'XmlTypeAttribute' is not found in " + instanceType.Name);
else
{
ns = ((XmlTypeAttribute)attr_arr[0]).Namespace;
Console.WriteLine("> extracted ns: '{0}'", ns);
}
//StringBuilder sb = new StringBuilder(ns);
//sb.Remove(ns.Length - 1, 1);
//ns = sb.ToString() + "n";
}
if (string.Compare(ns, _ns) != 0)
Console.WriteLine("*** ERR: namespace is not equal");
}
public override string NamespaceURI
{
get
{
if (NodeType == System.Xml.XmlNodeType.Element)
return ns;
else
return "";
}
}
}
}