65.9K
CodeProject 正在变化。 阅读更多。
Home

当 [XmlElement] 和 [XmlText] 结合使用时的 XML 序列化差异

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.78/5 (4投票s)

2015 年 2 月 14 日

CPOL

1分钟阅读

viewsIcon

29772

downloadIcon

104

本技巧展示了当可序列化类同时具有 [XmlElement] 和 [XmlText] 时,XML 序列化的差异。

引言

本技巧展示了当可序列化类同时具有 [XmlElement][XmlText] 时,XML 序列化的差异。

背景

XML 序列化可以通过各种方式和技术实现。 在本技巧中,我想展示我在使用声明为 [XmlElement] 的集合和声明为 [XmlText]string 的可序列化类时遇到的差异。

Using the Code

可序列化类

该类具有以下属性

  • 一个 string 作为属性 - [XmlAttribute]
  • 一个 string 作为文本属性 - [XmlText]
  • 一个 集合 作为元素 - [XmlElement]
    [XmlType(AnonymousType = true)]
    public class Person
    {
        [XmlAttribute("name")]
        public string Name { get; set; }

        [XmlText]
        public string Text { get; set; }
        
        [XmlElement("person")]
        public Collection<Person> Children { get; set; }

        public bool ShouldSerializeChildren()
        {
            return Children != null && Children.Count > 0;
        }

        public string Serialize()
        {
            var sw = new StringWriter();

            var serializer = new XmlSerializer(typeof(Person));
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            serializer.Serialize(sw, this, ns);

            return sw.ToString();
        }
    }

在未分配文本属性的情况下序列化类

仅分配 name 属性和 collection 元素。

            var person = new Person
            {
                Name = "name",
                Children =
                    new Collection<Person>
                    {
                        new Person {Name = "child1", Text = "child1Text"},
                        new Person {Name = "child2", Text = "child2Text"}
                    }
            };

            var personWithoutText = person.Serialize();

            Console.WriteLine("Person without text attribute has new lines:");
            Console.WriteLine("-------------------------------------------");
            Console.WriteLine(personWithoutText);
            Console.WriteLine();

结果

结果将是一个带有集合项之间换行的漂亮缩进的 XML。

<?xml version="1.0" encoding="utf-16"?>
<Person name="name">
  <person name="child1">child1Text</person>
  <person name="child2">child2Text</person>
</Person>

分配文本属性后序列化类

person.Text = "text";

            var personWithTextAttribue = person.Serialize();
            Console.WriteLine("Person with text attribute has no new lines:");
            Console.WriteLine("-------------------------------------------");
            Console.WriteLine(personWithTextAttribue);

            Console.ReadLine();

结果

结果将是一个没有集合项之间换行的 XML。

<?xml version="1.0" encoding="utf-16"?>
<Person name="name">text<person name="child1">child1Text</person>
<person name="child2">child2Text</person></Person>

结论

我找到的解决方法是,确保可序列化类中没有文本属性。

关注点

为什么我将集合属性声明为 XmlElement

如果集合未声明为 XmlElement,则其项将编码为以属性名称命名的元素下嵌套的元素序列。(请参阅 MSDN 中的 XmlElementAttribute

类似这样的东西

<myserializableclass>
    <wrappingelement>
        <item>item1</item>
        <item>item2</item>
        <item>item3</item>
    <myserializableclass>
</myserializableclass>

为了避免元素包装集合的项,我将集合声明为 [XmlElement]
序列化结果将是

<MySerializableClass>
    <item>item1</item>
    <item>item2</item>
    <item>item3</item>
 </MySerializableClass>

历史

  • 2015 年 2 月 14 日:初始版本
  • 2015 年 2 月 17 日:编辑结论并更新代码(修复了命名空间和 XML 属性)
© . All rights reserved.