【问题标题】:.NET Serialize XmlNode problem.NET 序列化 XmlNode 问题
【发布时间】:2010-01-07 14:19:07
【问题描述】:

所以我试图简单地装饰一个类以将其序列化为 XML。这是我的问题的一个例子。

[XmlElement("Dest")]
    public XmlNode NewValue { get; set; }

这里真正的问题是,有时在此实现中 XmlNode 可以是 XmlElement 或 XmlAttribute。当它是一个元素时,这段代码可以正常工作,但是当它作为一个属性出现时,序列化程序会抛出以下错误:

System.InvalidOperationException:无法将 XmlAttribute 类型的节点写入元素值。使用带有 XmlNode 或 XmlAttribute 数组的 XmlAnyAttributeAttribute 将节点写入属性。

我尝试了 XmlAnyAttribute,但也失败了。简单来说,如何序列化一个 XmlNode?​​p>

为了记录,我在下面标记了正确的答案。你有点得破解它。这大致是我自己实现的,以防其他人遇到这个问题。

    [XmlIgnore()]
    public XmlNode OldValue { get; set; }

    [XmlElement("Dest")]
    public XmlNode SerializedValue
    {
        get
        {
            if (OldValue == null)
            {
                return null;
            }
            if (OldValue.NodeType == XmlNodeType.Attribute)
            {
                XmlDocumentFragment frag = OldValue.OwnerDocument.CreateDocumentFragment();

                XmlElement elem = (frag.OwnerDocument.CreateNode(XmlNodeType.Element, "SerializedAttribute", frag.NamespaceURI) as XmlElement);

                elem.SetAttribute(OldValue.Name, OldValue.Value);

                return elem;
            }
            else
            {
                return OldValue;
            }
        }
        set
        {
            if (value == null)
            {
                OldValue = null;
                return;
            }
            if ((value.Attributes != null) && (value.NodeType == XmlNodeType.Element) && ((value.ChildNodes == null) || (value.ChildNodes.Count == 0)))
            {
                OldValue = value.Attributes[0];
            }
            else
            {
                OldValue = value;
            }
        }
    }

【问题讨论】:

  • 您希望它如何将属性序列化为节点?
  • 我知道 XmlElement 尝试序列化它是错误的,但那里没有 XmlNode 选项。由于 XmlAttribute 类是 XmlNode 类的子类,我希望它能够很好地处理它。

标签: c# .net xml xml-serialization serialization


【解决方案1】:

你可以尝试破解它(我同意它不是很好):

XmlNode v;

[XmlElement("Dest")]
public XmlNode NewValue { get{return v as XmlElement;} set{v = value;} }

[XmlAttribute("Dest")]
public NewValue { get{return v as XmlAttribute;} set{v = value;} }

【讨论】:

    【解决方案2】:

    您将 Xml 序列化与 XmlNodes 混合在一起似乎很奇怪,就像您说的那样,节点可以是属性或元素。通常,您会使用 XmlDocument.Save() 函数将 XmlNode 序列化为 XmlDocument 的一部分。

    我认为将 XmlNode 序列化为字符串可能更容易。可能是这样的:

    [XmlIgnore]
    public XmlNode NewValue { get; set; }
    
    [XmlElement("Dest")]
    public string NewValueString { get; set; }
    { 
        get { return NewValue.OuterXml; } // Edit: this property can't directly
        set { NewValue.OuterXml = value; } // set OuterXml
    }
    

    大量编辑:

    三思而后行……

    您正在混合使用两种不同的方式来处理 Xml,并且没有直接的方法可以使其正常工作。

    您不能将 Xml 序列化与 XmlNode、XmlAttribute 或 XmlElement 类型的属性一起使用。 XmlNode 及其子类没有 Xml 序列化所需的公共无参数构造函数。它们只能通过 XmlDocument 创建。此外,Xml 序列化通过反射和保存所有公共 get/set 属性来工作,而 XmlNode 和子类没有为此设计的属性。

    你仍然可以将 XmlNode 序列化为一个字符串(你不能像我上面展示的那样直接实现它)然后你必须在 xml 反序列化之后执行一些后处理步骤来重新创建 XmlNode。

    但同样,您混合了两种不同的处理 Xml 的方式,这在我心中引发了一些警告。

    【讨论】:

    • 感谢您的回答,但是,A. OuterXml 属性是只读的。你不能设置它的价值。 B. 即使可以,XmlAttribute 子类也不支持此属性。
    【解决方案3】:

    由于您不能混合和匹配默认机制,您很可能需要编写自己的序列化程序。通过这样做,您可以使用围绕对象的逻辑语句切换代码以导出/导入数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-08
      • 2011-11-12
      • 2018-04-23
      • 1970-01-01
      相关资源
      最近更新 更多