我的问题如下。
我有一个由命名空间版本化的xml。我想将这个收到的xml序列化到相应的对象中,但我知道这样做的唯一方法就是我必须处理xml两次。首先发现命名空间,然后根据发现的命名空间序列化到正确类型的对象。这对我来说似乎非常低效,并且必须有某种方式使用泛型或其他东西来获取适当类型的对象,而不使用'if namespace == x然后序列化到'检查。
以下是我知道完成此任务的唯一方法示例。是否有更好或更有效的方式?
由于
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.Linq;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace TestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod3()
{
//Build up an employee object to xml
Schema.v2.Employee employee = new Schema.v2.Employee { FirstName = "First", LastName = "Last" };
string xml = employee.ObjectToXml<Schema.v2.Employee>();
//Now pretend I don't know what type I am receiving.
string nameSpace = GetNamespace(xml);
Object newemp;
if (nameSpace == "Employee.v2")
newemp = XmlSerializationExtension.XmlToObject<Schema.v2.Employee>(null, xml);
else
newemp = XmlSerializationExtension.XmlToObject<Schema.v1.Employee>(null, xml);
// Check to make sure that the type I got was what I made.
Assert.AreEqual(typeof(Schema.v2.Employee), newemp.GetType());
}
public string GetNamespace(string s)
{
XDocument z = XDocument.Parse(s);
var result = z.Root.Attributes().
Where(a => a.IsNamespaceDeclaration).
GroupBy(a => a.Name.Namespace == XNamespace.None ? String.Empty : a.Name.LocalName,
a => XNamespace.Get(a.Value)).
ToDictionary(g => g.Key,
g => g.First());
foreach (System.Xml.Linq.XNamespace item in result.Values)
if (item.NamespaceName.Contains("Employee")) return item.NamespaceName;
return String.Empty;
}
}
public static class XmlSerializationExtension
{
public static string ObjectToXml<T>(this T Object)
{
XmlSerializer s = new XmlSerializer(Object.GetType());
using (StringWriter writer = new StringWriter())
{
s.Serialize(writer, Object);
return writer.ToString();
}
}
public static T XmlToObject<T>(this T Object, string xml)
{
XmlSerializer s = new XmlSerializer(typeof(T));
using (StringReader reader = new StringReader(xml))
{
object obj = s.Deserialize(reader);
return (T)obj;
}
}
}
}
namespace Schema.v1
{
[XmlRoot(ElementName = "Employee", Namespace= "Employee.v1", IsNullable = false)]
public class Employee
{
[XmlElement(ElementName = "FirstName")]
public string FirstName { get; set; }
[XmlElement(ElementName = "LastName")]
public string LastName { get; set; }
}
}
namespace Schema.v2
{
[XmlRoot(ElementName = "Employee", Namespace = "Employee.v2", IsNullable = false)]
public class Employee
{
[XmlAttribute(AttributeName = "FirstName")]
public string FirstName { get; set; }
[XmlAttribute(AttributeName = "LastName")]
public string LastName { get; set; }
}
}
答案 0 :(得分:1)
两个建议:
首先,也许根本不这样做。如果要进行序列化,除非调用者指定模式,否则首选一种方法而不是另一种方法。
其次,不要解析XML以进行发现;只需在文件的前100个字节内(或者说,你需要去获取信息)进行“Employee.v2”和“Employee.v1”的字符串匹配。这应该有效,除非这些将成为您数据中的常见字符串。