XML反序列化:对象具有默认值

时间:2012-07-26 07:05:58

标签: c# .net xml serialization


我的XML序列化程序有一种奇怪的行为 读取XML并将其反序列化为对象后,所有属性都将设置为默认值,而不是xml文件中声明的值。
序列化程序不会抛出异常并正常运行。 xml文件已正确形成并适合类结构 任何人都知道这可能是什么,或者我如何找到问题的根源? 谢谢

编辑: 我没有告诉你整个故事。问题是,我得到的XML来自另一个组件。我能够反序列化XML文件,现在我得到了一个不同的格式。由于文件大约有3000行,我无法发布整个代码。但这就是区别:
deserializable:

<?xml version="1.0" encoding="utf-8"?>
<rootElem xmlns:cfg="namespace1" xmlns:office="namespace2" xmlns="namespace3">
  <Prop1 xmlns="">6</Prop1>
  <Prop2 xmlns="">string</Prop2>
</rootElem>

不可反序列化

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<rootElem xmlns:cfg="namespace1" xmlns:office="namespace2" xmlns="namespace3">
  <Prop1>6</Prop1>
  <Prop2>string</Prop2>
</rootElem>

我真的不明白为什么我可以解组第一个例子,因为每个元素中的xmlns标记以及为什么我不能解组第二个... ...

edit2: 刚刚意识到只有顶级元素才能获得这些奇怪的xmlns =“”属性。但是C#类声明与所有其他类没有什么不同......这很奇怪。

C#类是这样的:

using namespace1;

namespace namespace3
{
  [System.SerializableAttribute()]
  [System.ComponentModel.DesignerCategoryAttribute("code")]
  [System.Xml.Serialization.XmlTypeAttribute(Namespace="namespace3")]
  [System.Xml.Serialization.XmlRootAttribute(Namespace="namespace3", IsNullable=true)]
  public partial class rootElem: BaseObject
  {
    [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public int Prop1
    {
      //...
    }
  }
}

2 个答案:

答案 0 :(得分:1)

一个具体的例子(c#ad xml)将在这里走很长的路。最有可能的一个:

  • 这些名称不是xml和c#之间的精确(区分大小写)匹配(允许通过属性等进行名称覆盖)
  • xml属性/元素之间存在混淆
  • xml名称空间存在差异(通常,存在于xml中,缺少c#)

通过编辑,它变得更加清晰。 Xml命名空间非常重要; <foo xmlns="abc"/><foo/>完全无关。此外,xml名称空间继承,因此在:

<rootElem xmlns:cfg="namespace1" xmlns:office="namespace2" xmlns="namespace3">
<Prop1>6</Prop1>
<Prop2>string</Prop2>
</rootElem>

Prop1Prop2属于他们从父级继承的namespace3命名空间。为了使c#绝对清楚你希望它们位于子命名空间(而不是空命名空间),告诉它

[Serializable]
[DesignerCategory("code")]
[XmlType(Namespace = Namespace3)]
[XmlRoot(Namespace = Namespace3, IsNullable = true)]
public partial class rootElem
{
    private const string Namespace3 = "namespace3"; // to avoid repetition

    [XmlElement(Namespace = Namespace3)]
    public int Prop1 { get; set; }
}

答案 1 :(得分:0)

经过进一步调查后,我找到了问题所在。我仍然不明白为什么序列化程序的行为方式如此。 到目前为止,我理解命名空间的删除,您必须定义“xmlns”属性,而不使用前缀来设置默认命名空间(W3Schools)。正如我的问题所述,它被定义(除了其他命名空间):

<rootElem xmlns:cfg="namespace1" xmlns:office="namespace2" xmlns="namespace3">

由于根元素的所有直接子元素都声明了xmlns属性,我的解释是无法找到默认命名空间。
所以我所做的是明确定义根元素的命名空间,以便生成根元素:

<root:rootElem xmlns:cfg="namespace1" xmlns:office="namespace2" xmlns:root="namespace3">

瞧,xml已正确生成(xmlns属性已从直接子节点中删除),并且序列化程序能够读取数据。
但仍然存在一些问题:

  • 为什么序列化程序没有使用默认值正确生成xml 命名空间?
  • 如果序列化程序无法读取数据并将其放入我的实例(为什么要创建一个“空”实例),我会发生异常