【问题标题】:How to serialize attribute on a property or skip a class hierarchy如何序列化属性上的属性或跳过类层次结构
【发布时间】:2016-08-03 14:14:47
【问题描述】:

我有一个使用 XmlSerializer 序列化的类。除了其他属性之外,我还需要向对象添加一大块预构建的 xml。我已经在这篇文章中问过如何处理那堆 xml:How to remove empty namespace attribute on manually added xml string when serializing object?

现在我需要为包含 xml 字符串的属性添加一个属性。我了解如何将属性添加到类而不是属性。如果我创建一个新类来保存属性,我会在输出中得到一个额外的层次结构。

这是我的简化代码:

public class Book
{
    public string Title { get; set; }

    public string Author { get; set; }

    public XmlElement Extension { get; set; }

    public Book()
    {
    }

    public void AddExtension()
    {
        string xmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" +
                                "<SpecialHandling>Some Value</SpecialHandling>" +
                           "</AdditionalInfo>";

        this.Extension = GetElement(xmlString);
    }

    public static XmlElement GetElement(string xml)
    {
        XmlDocument doc = new XmlDocument();

        doc.LoadXml(xml);

        return doc.DocumentElement;
    }
}

static void Main(string[] args)
{
    TestSerialization p = new TestSerialization();

    Book bookOne = new Book();

    bookOne.Title = "How to Fix Code";
    bookOne.Author = "Dee Bugger";

    bookOne.AddExtension();

    System.Xml.Serialization.XmlSerializer serializer = new XmlSerializer(typeof(Book), "http://www.somenamespace.com");

    using (var writer = new StreamWriter("C:\\BookReport.xml"))
    using (var xmlWriter = XmlWriter.Create(writer, new XmlWriterSettings { Indent = true }))
    {
        serializer.Serialize(xmlWriter, bookOne);
    }
}

它生成以下输出:

<?xml version="1.0" encoding="utf-8"?>
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.somenamespace.com">
  <Title>How to Fix Code</Title>
  <Author>Dee Bugger</Author>
  <Extension>
    <AdditionalInfo xmlns="http://www.somenamespace.com">
      <SpecialHandling>Some Value</SpecialHandling>
    </AdditionalInfo>
  </Extension>
</Book>

现在我需要向 Extension 添加一个属性,使 Extension 输出看起来像:

...
<Extension Modifier="ABC">
    <AdditionalInfo xmlns="http://www.somenamespace.com">
      <SpecialHandling>Some Value</SpecialHandling>
    </AdditionalInfo>
</Extension>

有没有办法改变 Book 类来做到这一点?我试图创建一个扩展类来保存修饰符属性和 xml 字符串的 XmlElement,但这导致了一个额外的级别:

public class Extension
{
    [XmlAttribute]
    public string Modifier { get; set; }

    [XmlElementAttribute("Extension")]
    public XmlElement ExtensionAsElement { get; set; }

    public Extension()
    {
    }

    public Extension(XmlElement extensionAsElement)
    {
        this.Modifier = "ABC";

        this.ExtensionAsElement = extensionAsElement;
    }
}

public class Book
{
    public string Title { get; set; }

    public string Author { get; set; }

    [XmlElementAttribute("Extension")]
    public Extension ExtensionObj { get; set; }

    public Book()
    {
    }

    public void AddExtension()
    {
        string xmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" +
                                "<SpecialHandling>Some Value</SpecialHandling>" +
                           "</AdditionalInfo>";

        this.ExtensionObj = new Extension(GetElement(xmlString));
    }

    public static XmlElement GetElement(string xml)
    {
        XmlDocument doc = new XmlDocument();

        doc.LoadXml(xml);

        return doc.DocumentElement;
    }
}

<?xml version="1.0" encoding="utf-8"?>
<Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.somenamespace.com">
  <Title>How to Fix Code</Title>
  <Author>Dee Bugger</Author>
  <Extension Modifier="ABC">
    <Extension>
      <AdditionalInfo xmlns="http://www.somenamespace.com">
        <SpecialHandling>Some Value</SpecialHandling>
      </AdditionalInfo>
    </Extension>
  </Extension>
</Book>

注意:这是我的代码的一个过度简化的示例,Book 类不是我的根。我只需要序列化,不需要反序列化。

【问题讨论】:

    标签: c# xml class serialization attributes


    【解决方案1】:

    您可以使用[XmlAnyElement("Extension")] 指定您的Extension 属性应作为元素&lt;Extension&gt; 本身插入XML 流,而不是作为元素的那个名字的。完成后,您将能够使用SetAttribute()GetAttribute() 在元素本身上设置属性。

    因此,您的 Book 类变为:

    public class Book
    {
        public string Title { get; set; }
    
        public string Author { get; set; }
    
        [XmlAnyElement("Extension")]
        public XmlElement Extension { get; set; }
    
        public Book()
        {
            this.Extension = new XmlDocument().CreateElement("Extension");
        }
    
        public Book AddExtension()
        {
            string innerXmlString = "<AdditionalInfo xmlns=\"http://www.somenamespace.com\">" +
                                    "<SpecialHandling>Some Value</SpecialHandling>" +
                               "</AdditionalInfo>";
            if (Extension == null)
                // Since Extension is marked with [XmlAnyElement("Extension")], its value must
                // be an XmlElement named "Extension".  Its InnerXml can be anything.
                Extension = new XmlDocument().CreateElement("Extension");
            Extension.InnerXml = innerXmlString;
            return this;
        }
    
        const string ModifierName = "Modifier";
    
        [XmlIgnore]
        public string Modifier
        {
            get
            {
                if (Extension == null)
                    return null;
                return Extension.GetAttribute(ModifierName);
            }
            set
            {
                if (Extension == null)
                    AddExtension();
                if (value == null)
                    Extension.RemoveAttribute(ModifierName);
                else
                    Extension.SetAttribute(ModifierName, value);
            }
        }
    }
    

    并从以下内容创建 XML:

    var bookOne = new Book { Title = "How to Fix Code", Author = "Dee Bugger", Modifier = "AAA" }
        .AddExtension();
    

    产生结果:

    <Book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <Title>How to Fix Code</Title>
        <Author>Dee Bugger</Author>
        <Extension Modifier="AAA">
            <AdditionalInfo xmlns="http://www.somenamespace.com">
                <SpecialHandling>Some Value</SpecialHandling>
            </AdditionalInfo>
        </Extension>
    </Book>
    

    【讨论】:

    • 谢谢@dbc。我只看到 XmlAnyElement 用于不同类型的数组。这很有帮助,解决了我的问题!
    • 对不起,我以为我有:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多