当XML没有命名空间时,如何反序列化装有XmlRoot命名空间的类?
这个问题以前被问过,但答案不适用于我:所以这里是问题再次:)当XML没有命名空间时,如何反序列化装有XmlRoot命名空间的类?
我真的有麻烦试图反序列化一些XML,并希望有人可以提供一些援助。我读过很多类似的帖子,但我无法解决这个问题。
这里是XML
<register-account success="false">
<user-name>xxxxx</user-name>
<password>fghgh</password>
<email>[email protected]</email>
</register-account>
类我试图反序列化到:
[Serializable, XmlRoot(ElementName = "register-account", Namespace = "MyNamespace")]
[XmlType("register-account")]
public class RegisterAccountResponse
{
[XmlAttribute("success")]
public bool Success { get; set; }
/// <summary>
/// Gets or sets the Tennant email address
/// </summary>
[XmlElement("email")]
public string Email { get; set; }
/// <summary>
/// Gets or sets the tennant password
/// </summary>
[XmlElement("password")]
public string Password { get; set; }
/// <summary>
/// Gets or sets the Tennant username
/// </summary>
[XmlElement("user-name")]
public string Username { get; set; }
}
反序列化方法
public static T Deserialize<T>(string data) where T : class
{
var ser = new XmlSerializer(typeof(T));
using (var sr = new StringReader(data))
{
return (T)ser.Deserialize(sr);
}
}
反序列化方法调用
var data = Helper.Deserialize<RegisterAccountResponse>(xml);
例外:
有XML文档中的误差(1,2)。 ---> System.InvalidOperationException:不是预期的。在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()
内部异常如下:
<register-account xmlns=''> was not expected.
的问题的答案是从类中删除的命名空间(除去Namespace =“MyNamespace”)。然而,该类是使用xsd.exe自动生成的非常大的库的一部分。我不想在生成的类中更改任何内容。是否仍然可以解决这个问题而不必修改类?
那么,如果你不能或不想改变代码,那么你必须xslt转换你的xml以在需要的地方添加一些命名空间。这将有助于解串器反序列化文档。
问候。
我无法更改反序列化代码吗?或者更改传入的xml以注入命名空间?我怎么能这样做 – 2012-03-29 18:21:57
我不这么认为你可以避免已经写入属性类的名称空间声明。但您可以使用XSLT更改包含的xml。它可能需要对XSLT进行一些研究,因为它是一种标记语言,用于设置xml.http://support.microsoft.com/kb/307322/en-us/或http://stackoverflow.com/questions/144713/add- a-namespace-to-elements-using-xslt – 2012-03-30 05:01:01
这个答案是不正确的。 xslt是不需要的。 @Amine - 你可以做你想做的。看到我的答案。 http://stackoverflow.com/a/10020010/48082 – Cheeso 2012-04-04 22:23:51
有没有需要修改这个问题而无需修改类?
是的。
.NET有一个名为XmlAttributeOverrides的类,它是专门为此目的而设计的。 您可以在运行时覆盖代码中存在的属性。
以下修改的Deserialize实用程序方法将使用您提供的XML正确反序列化您提供的类的实例,而无需对其进行修改。没有XSLT。
public static T DeserializeWithNoRootNamespace<T>(string data)
where T : class
{
/* Each overridden field, property, or type requires
an XmlAttributes object. We are overriding the serialization
of the XmlRoot on the type, so we need one XmlAttributes collection. */
var attrs = new XmlAttributes();
/* Create an XmlRootAttribute to override the XmlRoot in-line attr.
The override will use no namespace. */
var root = new XmlRootAttribute("register-account");
// set the XmlRoot on the XmlAttributes collection.
attrs.XmlRoot= root;
// Create the XmlAttributeOverrides object.
var o = new XmlAttributeOverrides();
/* Map the attributes collection to the thing being
overriden (the class). */
o.Add(typeof(T), attrs);
// create the serializer, specifying the overrides to use
var ser = new XmlSerializer(typeof(T), o);
using (var sr = new StringReader(data))
{
return (T)ser.Deserialize(sr);
}
}
上面的代码覆盖了XmlRoot属性。 XmlAttributeOverrides通用性足以允许覆盖任何要反序列化的类的xml序列化属性。你的情况没有必要。
PS:的[Serializable]
属性你装饰你的类,则不需要。这是一个常见的错误,将其应用于将被XML序列化和反序列化的类。但它是无关的,因此是错误的。
这是一个interresting,有了这段代码,我设法覆盖了我的XML命名空间,也就是说,我的模式有一个名称空间,但由于某种原因,我必须读取的XML文件具有不同的供应商名称空间。 但是,我可以从文件中读取命名空间,然后在我的反序列化中覆盖它,并从文件中按元素反序列化元素。 但是..很多运行时代码正在进行: 'test.vshost.exe'(CLR v4.0.30319:test.vshost.exe):Loaded'Microsoft.GeneratedCode'。 而且速度很慢..有没有其他方法可以做到这一点? – neslekkiM 2015-06-09 13:51:50
假设这是整个XML,那么您显示的XML没有名称空间(没有xmlns声明)。因此,将它从类的序列化参数中移除是有意义的......否则,请通过XSD重新生成类,以使其不需要名称空间即可生成。 – Reddog 2012-03-29 18:14:12
我不认为XSD.exe支持生成没有名称空间属性的类。 – 2012-03-29 18:34:14