Xmlserializer 到 C# 对象,存储原始 XML 元素 [英] Xmlserializer to C# object, store original XML element

查看:72
本文介绍了Xmlserializer 到 C# 对象,存储原始 XML 元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,是否可以将原始 XML 元素存储在 C# 类中?

Is it possible to store the original XML element in a C# class, for example?

原始 XML:

 <data someattributea="" someattributeb="" someattributec="" />

C#

using System;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace Xml2CSharp
{
    [XmlRoot(ElementName="data")]
    public class Data {
        [XmlAttribute(AttributeName="someattributea")]
        public string Someattributea { get; set; }
        [XmlAttribute(AttributeName="someattributeb")]
        public string Someattributeb { get; set; }
        [XmlAttribute(AttributeName="someattributec")]
        public string Someattributec { get; set; }

        public sourceXML { get; set; }    //this would return <data someattributea="" someattributeb="" someattributec="" />

    }

}

我知道我可以再次反序列化该类,但某些 XML 对象在设计时未知.

I understand I could deserialize the class again but some XML objects are unknown at design time.

推荐答案

如果您确实需要捕获有关 元素的所有内容,包括元素名称和命名空间本身 转换为字符串文字,您需要实现 IXmlSerializable 并手动序列化您的 Data 类型.例如,这是一个原型实现:

If you really need to capture everything about the <data /> element including the element name and namespace itself into a string literal, you will need to implement IXmlSerializable and serialize your Data type manually. For instance, here is a prototype implementation:

[XmlRoot(ElementName = ElementName)]
public class Data : IXmlSerializable
{
    public const string ElementName = "data";

    XElement element = new XElement((XName)ElementName);

    public string Someattributea
    {
        get { return (string)element.Attribute("someattributea"); }
        set { element.SetAttribute("someattributea", value); }
    }

    public string Someattributeb
    {
        get { return (string)element.Attribute("someattributeb"); }
        set { element.SetAttribute("someattributeb", value); }
    }

    public string Someattributec
    {
        get { return (string)element.Attribute("someattributec"); }
        set { element.SetAttribute("someattributec", value); }
    }

    public string SourceXML
    {
        get
        {
            return element.ToString();
        }
        set
        {
            if (value == null)
                throw new ArgumentNullException();
            element = XElement.Parse(value);
        }
    }

    #region IXmlSerializable Members

    public XmlSchema GetSchema() { return null; }

    public void ReadXml(XmlReader reader)
    {
        reader.MoveToContent();
        element = (XElement)XNode.ReadFrom(reader);
    }

    public void WriteXml(XmlWriter writer)
    {
        foreach (var attr in element.Attributes())
            writer.WriteAttributeString(attr.Name.LocalName, attr.Name.NamespaceName, attr.Value);
        foreach (var child in element.Elements())
            child.WriteTo(writer);
    }

    #endregion
}

public static class XElementExtensions
{
    public static void SetAttribute(this XElement element, XName attributeName, string value)
    {
        var attr = element.Attribute(attributeName);
        if (value == null)
        {
            if (attr != null)
                attr.Remove();
        }
        else
        {
            if (attr == null)
                element.Add(new XAttribute(attributeName, value));
            else
                attr.Value = value;
        }
    }
}

注意事项:

  • 读取时,完整的 XML 被加载到一个 XElement 成员中,该成员可以使用 LINQ to XML.因此,原始格式可能会丢失.

  • When reading, the complete XML is loaded into an XElement member which can be queried using LINQ to XML. As a result the original formatting may get lost.

IXmlSerializable 很难正确实现.请参阅实现 IXmlSerializable 的正确方法?如何正确实施 IXmlSerializable,了解有关如何执行的一些提示.

IXmlSerializable is tricky to implement correctly. See Proper way to implement IXmlSerializable? and How to Implement IXmlSerializable Correctly for some tips on how to do it.

已知属性 SomeattributeaSomeattributebSomeattributec 现在成为对底层 XElement 的代理查找.

The known properties Someattributea, Someattributeb and Someattributec now become surrogate lookups into the underlying XElement.

工作 .Net fiddle 这里.

Working .Net fiddle here.

另一方面,如果您只需要捕获未知元素、属性和文本内容,则可以使用 [XmlAnyAttribute], [XmlAnyElement][XmlText](前两个在 这个答案等效于IExtensibleDataObject的XmlSerializer 来自 Marc Gravell).这种方法产生了一个更简单的 Data 版本:

If, on the other hand, you only need to capture unknown elements, attributes and text content, you can use [XmlAnyAttribute], [XmlAnyElement] and [XmlText] (the first two of which are suggested in this answer to XmlSerializer equivalent of IExtensibleDataObject by Marc Gravell). This approach results in a much simpler version of Data:

[XmlRoot(ElementName = "data")]
public class Data
{
    [XmlAttribute(AttributeName = "someattributea")]
    public string Someattributea { get; set; }
    [XmlAttribute(AttributeName = "someattributeb")]
    public string Someattributeb { get; set; }
    [XmlAttribute(AttributeName = "someattributec")]
    public string Someattributec { get; set; }

    [XmlAnyAttribute]
    public XmlAttribute[] Attributes { get; set; }

    [XmlAnyElement]
    [XmlText] // Captures mixed content at the root level as well as child elements.
    public XmlNode[] ChildNodes { get; set; }
}

工作 .Net fiddle #2 这里.

Working .Net fiddle #2 here.

这篇关于Xmlserializer 到 C# 对象,存储原始 XML 元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆