.net 当XML没有名称空间时,如何反序列化用XmlRoot名称空间修饰的类?

.net 当XML没有名称空间时,如何反序列化用XmlRoot名称空间修饰的类?,.net,xml,xml-serialization,.net,Xml,Xml Serialization,以前有人问过这个问题,但答案对我来说并不适用:所以问题又来了:) 我在尝试反序列化一些XML时遇到了真正的困难,希望有人能提供一些帮助。我读过很多类似的帖子,但我无法解决这个问题 这是XML <register-account success="false"> <user-name>xxxxx</user-name> <password>fghgh</password> <email>test@example.c

以前有人问过这个问题,但答案对我来说并不适用:所以问题又来了:)

我在尝试反序列化一些XML时遇到了真正的困难,希望有人能提供一些帮助。我读过很多类似的帖子,但我无法解决这个问题

这是XML

<register-account success="false">
  <user-name>xxxxx</user-name>
  <password>fghgh</password>
  <email>test@example.com</email>
</register-account>

xxxxx
fghgh
test@example.com
我试图反序列化到的类:

[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; }
}
[Serializable,XmlRoot(ElementName=“register account”,Namespace=“MyNamespace”)]
[XmlType(“注册账户”)]
公共类注册表帐户响应
{
[XmlAttribute(“成功”)]
公共bool成功{get;set;}
/// 
///获取或设置Tennant电子邮件地址
/// 
[XmlElement(“电子邮件”)]
公共字符串电子邮件{get;set;}
/// 
///获取或设置坦能密码
/// 
[XmlElement(“密码”)]
公共字符串密码{get;set;}
/// 
///获取或设置Tennant用户名
/// 
[XmlElement(“用户名”)]
公共字符串用户名{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);
    }
}
publicstatict反序列化(字符串数据),其中T:class
{
var ser=新的XmlSerializer(typeof(T));
使用(var sr=新的StringReader(数据))
{
返回(T)序列反序列化(sr);
}
}
反序列化方法调用

var data = Helper.Deserialize<RegisterAccountResponse>(xml);
var data=Helper.Deserialize(xml);
例外情况:

XML文档(1,2)中有错误。--> System.InvalidOperationException:不应为。在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderData.Read5_data()

内部异常如下所示:

<register-account xmlns=''> was not expected.
不是预期的。

问题的答案是从类中删除名称空间(remove namespace=“MyNamespace”)。但是,该类是使用xsd.exe自动生成的非常大的库的一部分。我不想更改生成的类中的任何内容。在不修改类的情况下仍然可以解决这个问题吗

如果您不能或不想更改代码,那么您必须使用xslt来转换xml,以便在需要时添加一些名称空间。这将有助于反序列化程序对文档进行反序列化


问候。

是否仍有办法在不修改类的情况下解决此问题?

.NET有一个名为XmlAttributeOverrides的类,它就是为此而设计的。 您可以在运行时重写代码中存在的属性

下面修改的反序列化实用程序方法将使用您提供的XML正确地反序列化您提供的类的实例,而不需要修改任何一个。也没有XSLT

publicstatict反序列化为norootnamespace(字符串数据)
T:在哪里上课
{
/*每个重写的字段、属性或类型都需要
XmlAttributes对象。我们正在重写序列化
类型上的XmlRoot,因此我们需要一个XmlAttributes集合*/
var attrs=新的XmlAttributes();
/*创建XmlRootAttribute以重写XmlRoot内嵌属性。
重写将不使用命名空间*/
var root=新的XmlRootAttribute(“注册帐户”);
//在XmlAttributes集合上设置XmlRoot。
attrs.XmlRoot=root;
//创建XmlAttributeOverrides对象。
var o=新的XmlAttributeOverrides();
/*将属性集合映射到正在处理的对象
重写(类)*/
o、 添加(类型(T),属性);
//创建序列化程序,指定要使用的覆盖
var ser=新的XmlSerializer(typeof(T),o);
使用(var sr=新的StringReader(数据))
{
返回(T)序列反序列化(sr);
}
}
上面的代码覆盖XmlRoot属性。XmlAttributeOverrides足够通用,允许重写要反序列化的类的任何部分上的xml序列化属性。这在你的情况下是不必要的


ps:不需要装饰类的
[Serializable]
属性。将其应用于将被XML序列化和反序列化的类是一个常见错误。但这是无关的,因此是错误的

假设这是整个XML,那么您显示的XML没有名称空间(没有xmlns声明)。因此,从类的序列化参数中删除它是有意义的。。。或者,通过XSD重新生成类,使其在没有命名空间的情况下生成。我认为XSD.exe不支持在没有命名空间属性的情况下生成类。我不能更改反序列化代码吗?或者更改传入的xml以注入名称空间?我不认为这样可以避免在类中作为属性编写的名称空间声明。但是您可以使用XSLT更改输入xml。它可能需要对XSLT进行一些研究,因为它是一种为xml设置样式的标记语言。或者这个答案是错误的。xslt不是必需的@胺-你可以做你想做的事。看看我的答案。感谢@Cheeso的澄清,我错过了重写东西的方法。这是一个相互测试,通过这段代码,我成功地重写了xml上的名称空间,也就是说,我的模式有一个名称空间,但由于某种原因,我必须读取的xml文件在不同的供应商之间有不同的名称空间。但是有了它,我可以从文件中读取名称空间,然后在反序列化中重写它,从而从文件中逐个元素反序列化。但是正在生成大量运行时代码:“test.vshost.exe”(CLR v4.0.30319:test.vshost.exe):加载了“Microsoft.GeneratedCode”。而且速度非常慢。。还有其他方法吗?