深度解析XML的组织与类映射

2019-05-06 01:15栏目:编程程序

率先做个大约的总括,XML包罗的因素有XmlElement,XmlAttribute ,InnerText。

  • 开始
  • 最简便的应用XML的秘技
  • 类型定义与XML结构的炫彩
  • 使用 XmlElement
  • 使用 XmlAttribute
  • 使用 InnerText
  • 重命名节点名称
  • 列表和数组的连串化
  • 列表和数组的做为数据成员的连串化
  • 品类承袭与反连串化
  • 反类别化的实战操练
  • 反体系化的选用总计
  • 免除无需体系化的分子
  • 强制钦定成员的系列化顺序
  • 自定义类别化行为
  • XML的行使提议

重命名节点名称

看过前边多少个示范,大家应该能开掘:通过连串化获得的XmlElement和XmlAttribute都与项指标数额成员要么项目同名。 但是有时候大家得以期待让属性名与XML的节点名称不同,那么快要动用【重命名】的效果了,请看之下示例:

[XmlType("c4")]
public class Class4
{
    [XmlAttribute("id")]
    public int IntValue { get; set; }

    [XmlElement("name")]
    public string StrValue { get; set; }
}

系列化与反种类的调用代码前边早已一连来看,这里就回顾它们了。
运营结果如下(小编将结果做了换行管理):

<?xml version="1.0" encoding="utf-8"?>
<c4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    id="3">
    <name>Fish Li</name>
</c4>
---------------------------------------
IntValue: 3
StrValue: Fish Li

探望输出结果中的红字粗体字,再看看类型定义中的四个Attribute的多个字符串参数,小编想你能觉察规律的。

小结:XmlAttribute,XmlElement允许接受1个小名用来决定转换节点的称呼,类型的重命名用XmlType来促成。

归来顶部

 

原著章地址:

强制内定成员的体系化顺序

后面包车型地铁示范很想获得,作者精通先定义的StrValue,后定义的Url,但是在出口时的种种并是作者梦想的。 假诺您愿意调整种类化的出口顺序,能够参考下边包车型大巴示范代码(注意浅莲红粗体文字):

public class TestIgnore
{
    [XmlIgnore]    // 这个属性将不会参与序列化
    public int IntValue { get; set; }

    [XmlElement(Order = 1)]
    public string StrValue { get; set; }

    [XmlElement(Order = 2)]
    public string Url;
}

谈到底的出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<TestIgnore xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <StrValue>Fish Li</StrValue>
    <Url>http://www.cnblogs.com/fish-li/</Url>
</TestIgnore>

回来顶部

最简单易行的选取XML的不二等秘书技

由于.net framework针对XML提供了众多API,那几个API遵照差异的运用处境达成了不相同等级次序的卷入, 比如,大家能够直接选用XmlTextReader、XmlDocument、XPath来取数XML中的数据, 也能够接纳LINQ TO XML也许反种类化的措施从XML中读取数据。 那么,使用哪个种类办法最简便吗?

自家个人倾向于接纳种类化,反类别化的法子来行使XML。 选拔那种措施,小编借使牵挂怎么定义数据类型就能够了,读写XML各只须求1行调用就能够产生。 举个例子:

// 1. 首先要创建或者得到一个数据对象
Order order = GetOrderById(123);


// 2. 用序列化的方法生成XML
string xml = XmlHelper.XmlSerialize(order, Encoding.UTF8);


// 3. 从XML读取数据并生成对象
Order order2 = XmlHelper.XmlDeserialize<Order>(xml, Encoding.UTF8);

正是这么轻巧的事情,XML结构是怎么着的,笔者从来无须关切, 我只关注数据是或不是能保存以及下次是或不是能将它们读抽取来。

证实:XmlHelper是二个工具类,全体源代码如下: 

ca888会员登录 1ca888会员登录 2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

// 此处代码来源于博客【在.net中读写config文件的各种方法】的示例代码
// http://www.cnblogs.com/fish-li/archive/2011/12/18/2292037.html

namespace MyMVC
{
    public static class XmlHelper
    {
        private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding)
        {
            if( o == null )
                throw new ArgumentNullException("o");
            if( encoding == null )
                throw new ArgumentNullException("encoding");

            XmlSerializer serializer = new XmlSerializer(o.GetType());

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineChars = "rn";
            settings.Encoding = encoding;
            settings.IndentChars = "    ";

            using( XmlWriter writer = XmlWriter.Create(stream, settings) ) {
                serializer.Serialize(writer, o);
                writer.Close();
            }
        }

        /// <summary>
        /// 将一个对象序列化为XML字符串
        /// </summary>
        /// <param name="o">要序列化的对象</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>序列化产生的XML字符串</returns>
        public static string XmlSerialize(object o, Encoding encoding)
        {
            using( MemoryStream stream = new MemoryStream() ) {
                XmlSerializeInternal(stream, o, encoding);

                stream.Position = 0;
                using( StreamReader reader = new StreamReader(stream, encoding) ) {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// 将一个对象按XML序列化的方式写入到一个文件
        /// </summary>
        /// <param name="o">要序列化的对象</param>
        /// <param name="path">保存文件路径</param>
        /// <param name="encoding">编码方式</param>
        public static void XmlSerializeToFile(object o, string path, Encoding encoding)
        {
            if( string.IsNullOrEmpty(path) )
                throw new ArgumentNullException("path");

            using( FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write) ) {
                XmlSerializeInternal(file, o, encoding);
            }
        }

        /// <summary>
        /// 从XML字符串中反序列化对象
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="s">包含对象的XML字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>反序列化得到的对象</returns>
        public static T XmlDeserialize<T>(string s, Encoding encoding)
        {
            if( string.IsNullOrEmpty(s) )
                throw new ArgumentNullException("s");
            if( encoding == null )
                throw new ArgumentNullException("encoding");

            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            using( MemoryStream ms = new MemoryStream(encoding.GetBytes(s)) ) {
                using( StreamReader sr = new StreamReader(ms, encoding) ) {
                    return (T)mySerializer.Deserialize(sr);
                }
            }
        }

        /// <summary>
        /// 读入一个文件,并按XML的方式反序列化对象。
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>反序列化得到的对象</returns>
        public static T XmlDeserializeFromFile<T>(string path, Encoding encoding)
        {
            if( string.IsNullOrEmpty(path) )
                throw new ArgumentNullException("path");
            if( encoding == null )
                throw new ArgumentNullException("encoding");

            string xml = File.ReadAllText(path, encoding);
            return XmlDeserialize<T>(xml, encoding);
        }
    }
}

View Code

恐怕有人会说:小编动用XPath从XML读取数据也很轻易啊。

自己感觉那种说法有多少个限制条件:只须求从XML中读取少许的数据。
假设要一清二楚读取,用这种方法会写出一大堆的机械代码出来! 所以,作者十二分反感用那种格局从XML中读取全部多少。

回来顶部

public class Class3
{
    [XmlAttribute]
    public int IntValue { get; set; }
    [XmlText]
    public string StrValue { get; set; }
}

XML的使用建议

在服务端,C#代码中:

  1. 提出不用采纳低档其他XML API来利用XML,除非您是在统一打算框架或然通用类库。
  2. 提议使用种类化、反类别化的法子来扭转还是读取XML
    3. 当必要考虑使用XML时,先不用想着XML结构,先应该定义好数据类型。
    四. 列表节点不要选取[XmlElement],它会让全数子节点【晋级】,显得结构混乱。
    五. 举例期待系列化的XML长度小一些,能够行使[XmlAttribute],或许钦命2个越来越短小的外号。
  3. 毫无在三个列表中输出差别的数据类型,那样的XML结构的可读性糟糕。
  4. 全心全意选取UTF-八编码,不要选择GB2312编码。

在客户端,JavaScript代码中,小编不建议选择XML,而是提议接纳JSON来代替XML,因为:
壹. XML文书的尺寸比JSON要长,会占用更加多的互连网传输时间(究竟数据保存在服务端,所以传输是免不了的)
二. 在JavaScritp中选择XML比较辛勤(还有浏览器的包容难题),反而各样浏览器对JSON有丰硕好的支撑。

反种类化的采取计算

若果XML是由项目种类化得到那的,那么反系列化的调用代码是很轻巧的, 反之,假如要面对二个尚无项目标XML,就要求大家先规划一个(大概局地)类型出来, 那是3个逆向推导的进度,请参见以下步骤: 壹. 先是要分析任何XML结构,定义与之匹配的品类, 2. 万一XML结构有嵌套等级次序,则须求定义多少个品种与之相称, 三. 定义具体品种(一个层级下的XML结构)时,请参见以下表格。

XML形式

管理方法

补充表达

XmlElement

概念两脾质量

属性名与节点名字相称

XmlAttribute

[XmlAttribute] 加到属性上

 

InnerText

[XmlText] 加到属性上

贰个品种只能接纳2遍

节点重命名

根节点:[XmlType("testClass")] 成分节点:[XmlElement("name")] 属性节点:[XmlAttribute("id")] 列表子成分节点:[XmlArrayItem("Detail")] 列表成分本人:[XmlArray("Items")]

 

归来顶部

XML是一种很常见的数码保存方法,笔者每每用它来保存一些数据,或许是一些布置参数。 使用C#,大家得以借助.net framework提供的众多API来读取只怕创立修改这几个XML, 可是,不相同人采用XML的点子很有希望并差别样。 前天本身希图谈谈自身利用XML的一部分办法,供我们参考。

<?xml version="1.0" encoding="utf-8"?>
<XRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <List>
        <x1 aa="1" bb="2" />
        <x1 aa="3" bb="4" />
        <x2>
            <cc>ccccccccccc</cc>
            <dd>dddddddddddd</dd>
        </x2>
    </List>
</XRoot>
public class XBase { }
[XmlType("x1")]
public class X1 : XBase
{
    [XmlAttribute("aa")]
    public int AA { get; set; }
    [XmlAttribute("bb")]
    public int BB { get; set; }
}
[XmlType("x2")]
public class X2 : XBase
{
    [XmlElement("cc")]
    public string CC { get; set; }

    [XmlElement("dd")]
    public string DD { get; set; }
}
public class XRoot
{
    [XmlArrayItem(typeof(X1)),
    XmlArrayItem(typeof(X2))]
    public List<XBase> List { get; set; }
}

破除无需体系化的积极分子

暗许情形下,类型的有所公开的数据成员(属性,字段)在连串化时都会被输出, 倘诺希望消除有个别成员,能够用[XmlIgnore]来指出,例如:

public class TestIgnore
{
    [XmlIgnore]    // 这个属性将不会参与序列化
    public int IntValue { get; set; }

    public string StrValue { get; set; }

    public string Url;
}

系列化调用代码:

TestIgnore c1 = new TestIgnore { IntValue = 3, StrValue = "Fish Li" };
c1.Url = "http://www.cnblogs.com/fish-li/";

string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

输出结果如下:

<?xml version="1.0" encoding="utf-8"?>
<TestIgnore xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Url>http://www.cnblogs.com/fish-li/</Url>
    <StrValue>Fish Li</StrValue>
</TestIgnore>

回到顶部

类型定义与XML结构的照射

1经是1个新类型,笔者必然会果断的利用连串化和反种类化的主意来采用XML, 然则,有时在维护贰个老项目时,面对一堆唯有XML却不曾与之对应的C#品种时, 大家就必要依附XML结构来逆向推导C#类型,然后技艺应用种类化和反连串化的点子。 逆向推导的进度是劳动的,但是,类型推导出来未来,后边的事务就大概多了。

为了学会依照XML结构逆向推导类型,大家须求关心一下类型定义与XML结构的炫酷关系。 注意:有时候大家也会惦念XML结构对于传输量及可阅读性的影响,所以关切一下XML也是有必不可缺的。

此处有一个XML文件,是本身从Visual Sutdio的设置目录中找到的: ca888会员登录 3;)

什么样用反系列化的方法来读取它的数量吧,笔者在博客的末梢将交由完整的兑当代码。 今后,咱们还是看一下那一个XML有哪些特点呢。

<LinkGroup ID="sites" Title="Venus Sites" Priority="1500">

对于那一个节点的话,它蕴涵了多个数据项(属性):ID,Title,Priority。 那样的LinkGroup节点有多少个。 类似的还有Glyph节点。

<LItem URL="http://www.asp.net" LinkGroup="sites">ASP.NET Home Page</LItem>

LItem节点除了与LinkGroup有着近乎的数据(属性)之外,还蕴含着二个字符串:ASP.NET Home Page , 那是此外一种多少的寄放格局。

除此以外,LinkGroup和LItem都同意再现,大家能够用数组只怕列表(Array,List)来领会它们。

自己还开掘有个别嵌套关系:LinkGroup能够包括Glyph,Context包罗着Links,Links又带有了多个LItem。 不管如何嵌套,小编开采数目都以包括在3个多个的XML节点中。

就算用标准的单词来叙述它们,大家得以将ID,Title,Priority那多个数据项称为 XmlAttribute, LItem,LinkGroup节点称为 XmlElement,”ASP.NET Home Page“出现的岗位能够称呼 InnerText。 基本上,XML正是由那3类数据整合。

下边作者来演示怎么样选用那三种多少项。

归来顶部

排除无需连串化的分子

暗中认可意况下,类型的持有公开的数额成员(属性,字段)在连串化时都会被输出, 如若希望消除某个成员,可以用[XmlIgnore]来指出,例如:

public class TestIgnore
{
    [XmlIgnore]    // 这个属性将不会参与序列化
    public int IntValue { get; set; }

    public string StrValue { get; set; }

    public string Url;
}

连串化调用代码:

TestIgnore c1 = new TestIgnore { IntValue = 3, StrValue = "Fish Li" };
c1.Url = "http://www.cnblogs.com/fish-li/";

string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<TestIgnore xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Url>http://www.cnblogs.com/fish-li/</Url>
    <StrValue>Fish Li</StrValue>
</TestIgnore>

回到顶部

    • XmlAttribute

种类化去掉XML命名空间及申明头

在后面包车型客车身体力行中,大家会发觉有时很轻松的XML在加了命名空间及表明头以往,结构变复杂了,内容也变长了。 有些人看来它们大概两次三番认为格外别扭,举例:

<?xml version="1.0" encoding="utf-8"?>
<ClassB1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Test s="Fish Li">1,2,3,4,5</Test>
</ClassB1>

能否只体现存下边那样吗?

<ClassB1>
    <Test s="Fish Li">1,2,3,4,5</Test>
</ClassB1>

答案是早晚的,按上面包车型客车不二等秘书技修改本文的演示代码:

private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding)
{
    if( o == null )
        throw new ArgumentNullException("o");
    if( encoding == null )
        throw new ArgumentNullException("encoding");

    XmlSerializer serializer = new XmlSerializer(o.GetType());

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.NewLineChars = "rn";
    settings.Encoding = encoding;
    settings.IndentChars = "    ";

    // 不生成声明头
    settings.OmitXmlDeclaration = true;

    // 强制指定命名空间,覆盖默认的命名空间。
    XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
    namespaces.Add(string.Empty, string.Empty);

    using( XmlWriter writer = XmlWriter.Create(stream, settings) ) {
        serializer.Serialize(writer, o, namespaces);
        writer.Close();
    }
}

注解:去掉XML命名空间及注明头不影响反体系化。

再次来到顶部

自定义种类化行为

由于各个原因,大概必要我们友好支配体系化和反系列化的进程, 对于那种须要, .net framework也是支撑的,下边小编来演示如何那个历程。

只要自个儿今后有这么的类型定义:

public class TestClass
{
    public string StrValue { get; set; }

    public List<int> List { get; set; }
}

public class ClassB1
{
    public TestClass Test { get; set; }
}

测试代码:

TestClass test = new TestClass { StrValue = "Fish Li", List = new List<int> { 1, 2, 3, 4, 5 } };
ClassB1 b1 = new ClassB1 { Test = test };

string xml = XmlHelper.XmlSerialize(b1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("-----------------------------------------------------");

ClassB1 b2 = XmlHelper.XmlDeserialize<ClassB1>(xml, Encoding.UTF8);
Console.WriteLine("StrValue: "   b2.Test.StrValue);
foreach( int n in b2.Test.List )
    Console.WriteLine(n);

此时程序的输出结果如下:

<?xml version="1.0" encoding="utf-8"?>
<ClassB1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Test>
        <StrValue>Fish Li</StrValue>
        <List>
            <int>1</int>
            <int>2</int>
            <int>3</int>
            <int>4</int>
            <int>5</int>
        </List>
    </Test>
</ClassB1>
-----------------------------------------------------
StrValue: Fish Li
1
2
3
4
5

现今本身恐怕会想:TestClass那几个类太轻巧了,但它输出的XML长度复杂了点,能还是不能再短小一些,让网络传输地更加快呢?

在此处,作者想开了自定义种类化行为来实现,请看上边对TestClass的再度定义。

public class TestClass : IXmlSerializable
{
    public string StrValue { get; set; }

    public List<int> List { get; set; }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        return null;
    }

    public void ReadXml(XmlReader reader)
    {
        StrValue = reader.GetAttribute("s");

        string numbers = reader.ReadString();
        if( string.IsNullOrEmpty(numbers) == false )
            List = (from s in numbers.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    let n = int.Parse(s)
                    select n).ToList();
    }

    public void WriteXml(XmlWriter writer)
    {
        writer.WriteAttributeString("s", StrValue);
        writer.WriteString(string.Join(",", List.ConvertAll<string>(x => x.ToString()).ToArray()));
    }
}

雄起雌伏选择后边的测试代码,未来的出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<ClassB1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Test s="Fish Li">1,2,3,4,5</Test>
</ClassB1>
-----------------------------------------------------
StrValue: Fish Li
1
2
3
4
5

很显明,现在的种类化结果要比原先的结果小大多。 而且,测试代码中的反系列化的来得也标识,大家照例能够因而反体系化来读取它。

回来顶部

列表和数组的系列化

继续看示例代码:

Class4 c1 = new Class4 { IntValue = 3, StrValue = "Fish Li" };
Class4 c2 = new Class4 { IntValue = 4, StrValue = "http://www.cnblogs.com/fish-li/" };

// 说明:下面二行代码的输出结果是一样的。
List<Class4> list = new List<Class4> { c1, c2 };
//Class4[] list = new Class4[] { c1, c2 };

string xml = XmlHelper.XmlSerialize(list, Encoding.UTF8);
Console.WriteLine(xml);

// 序列化的结果,反序列化一定能读取,所以就不再测试反序列化了。

运营结果如下:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfC4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <c4 id="3">
        <name>Fish Li</name>
    </c4>
    <c4 id="4">
        <name>http://www.cnblogs.com/fish-li/</name>
    </c4>
</ArrayOfC4>

当今c4节点已经再一次现身了,显明,是大家愿意的结果。

但是,ArrayOfC四,这一个节点名看起来太出乎意料了,能还是不可能给它也重命名呢?
持续看代码,我得以定义多少个新的类型:

// 二种Attribute都可以完成同样的功能。
//[XmlType("c4List")]
[XmlRoot("c4List")]
public class Class4List : List<Class4> { }

然后,改一下调用代码:

Class4List list = new Class4List { c1, c2 };

运维结果如下:

<?xml version="1.0" encoding="utf-8"?>
<c4List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <c4 id="3">
        <name>Fish Li</name>
    </c4>
    <c4 id="4">
        <name>http://www.cnblogs.com/fish-li/</name>
    </c4>
</c4List>

小结:数组和列表都能从来类别化,如若要重命名根节点名称,必要创建3个新品类来落到实处。

重回顶部

    • XmlElement

使用 XmlElement

第二,笔者来定义3个类型:

public class Class1
{
    public int IntValue { get; set; }

    public string StrValue { get; set; }
}

下边是体系化与反连串的调用代码:

Class1 c1 = new Class1 { IntValue = 3, StrValue = "Fish Li" };
string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("---------------------------------------");

Class1 c2 = XmlHelper.XmlDeserialize<Class1>(xml, Encoding.UTF8);
Console.WriteLine("IntValue: "   c2.IntValue.ToString());
Console.WriteLine("StrValue: "   c2.StrValue);

运作结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Class1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <IntValue>3</IntValue>
    <StrValue>Fish Li</StrValue>
</Class1>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果突显,IntValue和StrValue那2个属性生成了XmlElement。

小结:暗许处境下(不加任何Attribute),类型中的属性也许字段,都会生成XmlElement。

再次回到顶部

重命名节点名称

看过前面几个示范,大家应该能窥见:通过种类化获得的XmlElement和XmlAttribute都与类型的数量成员要么项目同名。 然则有时候我们得以期待让属性名与XML的节点名称不一致样,那么快要动用【重命名】的功效了,请看之下示例:

[XmlType("c4")]
public class Class4
{
    [XmlAttribute("id")]
    public int IntValue { get; set; }

    [XmlElement("name")]
    public string StrValue { get; set; }
}

连串化与反连串的调用代码前面早已数十次看到,这里就简单它们了。 运营结果如下(笔者将结果做了换行管理):

<?xml version="1.0" encoding="utf-8"?>
<c4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    id="3">
    <name>Fish Li</name>
</c4>
---------------------------------------
IntValue: 3
StrValue: Fish Li

看望输出结果中的红字粗体字,再看看类型定义中的四个Attribute的三个字符串参数,笔者想你能开采规律的。

总计:XmlAttribute,XmlElement允许接受贰个别称用来调节调换节点的名称,类型的重命名用XmlType来落到实处。

再次回到顶部

阅读目录

    • InnerText

使用 InnerText

抑或来定义二个品类:

public class Class3
{
    [XmlAttribute]
    public int IntValue { get; set; }

    [XmlText]
    public string StrValue { get; set; }
}

小心,作者在StrValue上平添的两样的Attribute.

上面是连串化与反种类的调用代码: ca888会员登录 4

Class3 c1 = new Class3 { IntValue = 3, StrValue = "Fish Li" };
string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("---------------------------------------");

Class3 c2 = XmlHelper.XmlDeserialize<Class3>(xml, Encoding.UTF8);
Console.WriteLine("IntValue: "   c2.IntValue.ToString());
Console.WriteLine("StrValue: "   c2.StrValue);

运维结果如下(作者将结果做了换行管理):

<?xml version="1.0" encoding="utf-8"?>
<Class3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    IntValue="3">Fish Li</Class3>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果符合预期:StrValue属性在加多了[XmlText]从此将来,生成了叁个文书节点(InnerText)

计算:假设希望项目中的属性恐怕字段生成InnerText,需求在档案的次序的积极分子上用[XmlText]来指出。

回去顶部

列表和数组的种类化

继续看示例代码:

Class4 c1 = new Class4 { IntValue = 3, StrValue = "Fish Li" };
Class4 c2 = new Class4 { IntValue = 4, StrValue = "http://www.cnblogs.com/fish-li/" };

// 说明:下面二行代码的输出结果是一样的。
List<Class4> list = new List<Class4> { c1, c2 };
//Class4[] list = new Class4[] { c1, c2 };

string xml = XmlHelper.XmlSerialize(list, Encoding.UTF8);
Console.WriteLine(xml);

// 序列化的结果,反序列化一定能读取,所以就不再测试反序列化了。

运维结果如下:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfC4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <c4 id="3">
        <name>Fish Li</name>
    </c4>
    <c4 id="4">
        <name>http://www.cnblogs.com/fish-li/</name>
    </c4>
</ArrayOfC4>

今昔c4节点已经再现了,明显,是大家愿意的结果。

只是,ArrayOfC四,这几个节点名看起来太难以置信了,能还是无法给它也重命名呢? 继续看代码,小编得以定义3个新的花色:

// 二种Attribute都可以完成同样的功能。
//[XmlType("c4List")]
[XmlRoot("c4List")]
public class Class4List : List<Class4> { }

下一场,改一下调用代码:

Class4List list = new Class4List { c1, c2 };

运作结果如下:

<?xml version="1.0" encoding="utf-8"?>
<c4List xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <c4 id="3">
        <name>Fish Li</name>
    </c4>
    <c4 id="4">
        <name>http://www.cnblogs.com/fish-li/</name>
    </c4>
</c4List>

小结:数组和列表都能一贯系列化,要是要重命名根节点名称,须要创建一个新品类来贯彻。

回到顶部

强制内定成员的体系化顺序

前面的示范很想获得,小编明明先定义的StrValue,后定义的Url,不过在出口时的11并是笔者梦想的。
若是您期望调整系列化的出口顺序,可以参考上边包车型大巴言传身教代码(注意银灰粗体文字):

public class TestIgnore
{
    [XmlIgnore]    // 这个属性将不会参与序列化
    public int IntValue { get; set; }

    [XmlElement(Order = 1)]
    public string StrValue { get; set; }

    [XmlElement(Order = 2)]
    public string Url;
}

最终的出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<TestIgnore xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <StrValue>Fish Li</StrValue>
    <Url>http://www.cnblogs.com/fish-li/</Url>
</TestIgnore>

重临顶部

 

阅读目录

最简便易行的利用XML的章程

由于.net framework针对XML提供了诸多API,那个API依据分化的使用意况完毕了区别档次的卷入, 举个例子,大家得以一贯动用XmlTextReader、XmlDocument、XPath来取数XML中的数据, 也可以利用LINQ TO XML恐怕反类别化的主意从XML中读取数据。 那么,使用哪一类方法最简易吗?

小编个人倾向于选用体系化,反体系化的方式来利用XML。 选取那种办法,作者借使思量怎么定义数据类型就足以了,读写XML各只要求一行调用就能够到位。 比如:

// 1. 首先要创建或者得到一个数据对象
Order order = GetOrderById(123);


// 2. 用序列化的方法生成XML
string xml = XmlHelper.XmlSerialize(order, Encoding.UTF8);


// 3. 从XML读取数据并生成对象
Order order2 = XmlHelper.XmlDeserialize<Order>(xml, Encoding.UTF8);

就是这么轻松的作业,XML结构是怎么样的,笔者历来无须关注, 作者只关怀数据是不是能保存以及下次是或不是能将它们读抽出来。

表达:XmlHelper是三个工具类,全部源代码如下: ca888会员登录 5;)

 

或许有人会说:作者动用XPath从XML读取数据也相当粗略啊。 作者感到那种说法有贰个限制条件:只供给从XML中读取少许的多少。 假若要任何读取,用那种方法会写出一大堆的机械代码出来! 所以,小编卓殊反感用那种方法从XML中读取全体数据。

回到顶部

使用 InnerText

抑或来定义三个品类:

public class Class3
{
    [XmlAttribute]
    public int IntValue { get; set; }

    [XmlText]
    public string StrValue { get; set; }
}

留神,我在StrValue上扩充的不等的Attribute.

上边是系列化与反系列的调用代码: ca888会员登录 6

Class3 c1 = new Class3 { IntValue = 3, StrValue = "Fish Li" };
string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("---------------------------------------");

Class3 c2 = XmlHelper.XmlDeserialize<Class3>(xml, Encoding.UTF8);
Console.WriteLine("IntValue: "   c2.IntValue.ToString());
Console.WriteLine("StrValue: "   c2.StrValue);

运作结果如下(小编将结果做了换行管理):

<?xml version="1.0" encoding="utf-8"?>
<Class3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    IntValue="3">Fish Li</Class3>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果符合预期:StrValue属性在加码了[XmlText]自此,生成了多少个文本节点(InnerText)

总括:倘若指望项目中的属性大概字段生成InnerText,需求在档案的次序的成员上用[XmlText]来指出。

再次来到顶部

     列表成分能够是一模2样种档案的次序,也能够不是千篇壹律种档次(有些项目标派生类)。同时为列表成员内定七个[XmlArrayItem(typeof(XXX))]可完结二种派生类型混在一起输出。 

列表和数组的做为数据成员的连串化

第3,依然定义3个品类:

public class Root
{
    public Class3 Class3 { get; set; }

    public List<Class2> List { get; set; }
}

系列化的调用代码:

Class2 c1 = new Class2 { IntValue = 3, StrValue = "Fish Li" };
Class2 c2 = new Class2 { IntValue = 4, StrValue = "http://www.cnblogs.com/fish-li/" };

Class3 c3 = new Class3 { IntValue = 5, StrValue = "Test List" };

Root root = new Root { Class3 = c3, List = new List<Class2> { c1, c2 } };

string xml = XmlHelper.XmlSerialize(root, Encoding.UTF8);
Console.WriteLine(xml);

运营结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Class3 IntValue="5">Test List</Class3>
    <List>
        <Class2 IntValue="3">
            <StrValue>Fish Li</StrValue>
        </Class2>
        <Class2 IntValue="4">
            <StrValue>http://www.cnblogs.com/fish-li/</StrValue>
        </Class2>
    </List>
</Root>

若果这里须求为List和Class二的节点重命名,该如何是好呢?
假使继续行使前面介绍的不二等秘书诀,是没用的。

上边包车型地铁代码演示了怎么重命名列表节点的名号:

public class Root
{
    public Class3 Class3 { get; set; }

    [XmlArrayItem("c2")]
    [XmlArray("cccccccccccc")]
    public List<Class2> List { get; set; }
}

连串化的调用代码与前方完全同样,获得的出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Class3 IntValue="5">Test List</Class3>
    <cccccccccccc>
        <c2 IntValue="3">
            <StrValue>Fish Li</StrValue>
        </c2>
        <c2 IntValue="4">
            <StrValue>http://www.cnblogs.com/fish-li/</StrValue>
        </c2>
    </cccccccccccc>
</Root>

想不想把cccccccccccc节点去掉吧(直接出现c2节点)?
下边包车型大巴类型定义格局贯彻了那么些主见:

public class Root
{
    public Class3 Class3 { get; set; }

    [XmlElement("c2")]
    public List<Class2> List { get; set; }
}

出口结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Class3 IntValue="5">Test List</Class3>
    <c2 IntValue="3">
        <StrValue>Fish Li</StrValue>
    </c2>
    <c2 IntValue="4">
        <StrValue>http://www.cnblogs.com/fish-li/</StrValue>
    </c2>
</Root>

总计:数组和列表都在系列化时,暗中同意景况下会基于项目中的数据成员名称更换3个节点, 列表项会生成子节点,若是要重命名,能够应用[XmlArrayItem]和[XmlArray]来兑现。 还是能直接用[XmlElement]调节不生成列表的父节点。

归来顶部

使用 XmlElement

率先,笔者来定义多少个品类:

public class Class1
{
    public int IntValue { get; set; }

    public string StrValue { get; set; }
}

下边是系列化与反种类的调用代码:

Class1 c1 = new Class1 { IntValue = 3, StrValue = "Fish Li" };
string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("---------------------------------------");

Class1 c2 = XmlHelper.XmlDeserialize<Class1>(xml, Encoding.UTF8);
Console.WriteLine("IntValue: "   c2.IntValue.ToString());
Console.WriteLine("StrValue: "   c2.StrValue);

运作结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Class1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <IntValue>3</IntValue>
    <StrValue>Fish Li</StrValue>
</Class1>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果展现,IntValue和StrValue那3个属性生成了XmlElement。

小结:暗中认可意况下(不加任何Attribute),类型中的属性也许字段,都会生成XmlElement。

归来顶部

  • 开始
  • 最简易的应用XML的不2秘籍
  • 类型定义与XML结构的映照
  • 使用 XmlElement
  • 使用 XmlAttribute
  • 使用 InnerText
  • 重命名节点名称
  • 列表和数组的系列化
  • 列表和数组的做为数据成员的种类化
  • 品种传承与反类别化
  • 反连串化的实战演习
  • 反体系化的行使计算
  • 排除没有需要系列化的分子
  • 强制钦赐成员的类别化顺序
  • 自定义系列化行为
  • 连串化去掉XML命名空间及注脚头
  • XML的使用建议

     节点文本内容

反连串化的实战演习

接下去,大家将依靠前面介绍的知识点,用反种类化的措施来分析本文起初处贴出的这段XML: ca888会员登录 7

<DynamicHelp xmlns="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd vsdh.xsd">
    <LinkGroup ID="sites" Title="Venus Sites" Priority="1500">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <LinkGroup ID="Venus Private Forums" Title="Venus Private Forums" Priority="1400">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <LinkGroup ID="ASP.NET Forums" Title="ASP.NET 1.0 Public Forums" Priority="1200">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <Context>
        <Links>
            <LItem URL="http://www.asp.net/venus" LinkGroup="sites">Venus Home Page</LItem>
            <LItem URL="http://www.asp.net" LinkGroup="sites">ASP.NET Home Page</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=77" 
                    LinkGroup="Venus Private Forums">General Discussions</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=83" 
                    LinkGroup="Venus Private Forums">Feature Requests</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=78" 
                    LinkGroup="Venus Private Forums">Bug Reports</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=86" 
                    LinkGroup="Venus Private Forums">ASP.NET 2.0 Related issues</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=11" 
                    LinkGroup="ASP.NET Forums">Announcements</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=15" 
                    LinkGroup="ASP.NET Forums">Getting Started</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=18" 
                    LinkGroup="ASP.NET Forums">Web Forms</LItem>
        </Links>
    </Context>
</DynamicHelp>

那段XML的根成分是DynamicHelp,由此,我们要求定义2个门类,类名叫DynamicHelp。
再观望那段XML,它应当包蕴1个LinkGroup列表,和三个Context属性,所以能够如此定义那多个种类:

public class DynamicHelp
{
    [XmlElement]
    public List<LinkGroup> Groups { get; set; }

    public Context Context { get; set; }
}

public class LinkGroup { }

public class Context { }

再来看LinkGroup,它包含八个数据成员,以及三个子节点:Glyph,由此能够这么定义它们:

public class LinkGroup 
{
    [XmlAttribute]
    public string ID { get; set; }
    [XmlAttribute]
    public string Title { get; set; }
    [XmlAttribute]
    public int Priority { get; set; }

    public Glyph Glyph { get; set; }
}

public class Glyph
{
    [XmlAttribute]
    public int Collapsed { get; set; }
    [XmlAttribute]
    public int Expanded { get; set; }
}

LItem节点也简要,它就含有了U本田CR-VL,LinkGroup和1个文本节点,因而得以那样定义它:

public class LItem
{
    [XmlAttribute]
    public string URL { get; set; }
    [XmlAttribute]
    public string LinkGroup { get; set; }

    [XmlText]
    public string Title { get; set; }
}

Context节点也不复杂,就只包括了2个LItem列表,因而得以这么定义它:

public class Context 
{
    public List<LItem> Links { get; set; }
}

好了,类型都定义好了,再来试试反体系化:

DynamicHelp help = XmlHelper.XmlDeserializeFromFile<DynamicHelp>("Links.xml", Encoding.UTF8);

foreach( LinkGroup group in help.Groups )
    Console.WriteLine("ID: {0}, Title: {1}, Priority: {2}, Collapsed: {3}, Expanded: {4}",
        group.ID, group.Title, group.Priority, group.Glyph.Collapsed, group.Glyph.Expanded);

foreach( LItem item in help.Context.Links )
    Console.WriteLine("URL: {0}, LinkGroup: {1}, Title: {2}",
        item.URL.Substring(0, 15), item.LinkGroup, item.Title);

显示器呈现:

未处理的异常:  System.InvalidOperationException: XML 文档(4, 2)中有错误。 
---> System.InvalidOperationException: 不应有 
<DynamicHelp xmlns='http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd'>。

啊,抛非常了。
别急,看看那多少个说怎么。
接近是在说命名空间无法鉴定分别。
依赖十分的叙说,小编还要修改一下DynamicHelp的定义,改成那样:

[XmlRoot(Namespace = "http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd")]
public class DynamicHelp

再一次运维,结果如下:

ID: sites, Title: Venus Sites, Priority: 1500, Collapsed: 3, Expanded: 4
ID: Venus Private Forums, Title: Venus Private Forums, Priority: 1400, Collapsed: 3, Expanded: 4
ID: ASP.NET Forums, Title: ASP.NET 1.0 Public Forums, Priority: 1200, Collapsed: 3, Expanded: 4
URL: http://www.asp., LinkGroup: sites, Title: Venus Home Page
URL: http://www.asp., LinkGroup: sites, Title: ASP.NET Home Page
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: General Discussions
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: Feature Requests
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: Bug Reports
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: ASP.NET 2.0 Related issues
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Announcements
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Getting Started
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Web Forms

小结:依照XML结构推导类型时,要保管项指标档期的顺序结构与XML相配, 数据的存放格局得以经过[XmlElement],[XmlAttribute],[XmlText]办法来建议。

回去顶部

使用 InnerText

依旧来定义叁个类型:

public class Class3
{
    [XmlAttribute]
    public int IntValue { get; set; }

    [XmlText]
    public string StrValue { get; set; }
}

留神,小编在StrValue上加码的不如的Attribute.

下边是系列化与反连串的调用代码: ca888会员登录 8;)

运营结果如下(作者将结果做了换行管理):

<?xml version="1.0" encoding="utf-8"?>
<Class3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    IntValue="3">Fish Li</Class3>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果符合预期:StrValue属性在扩展了[XmlText]尔后,生成了叁个文件节点(InnerText)

小结:假设期望项目中的属性只怕字段生成InnerText,必要在类型的分子上用[XmlText]来指出。

回到顶部

品类承袭与反连串化

列表成分得以是均等种档期的顺序,也足以不是均等种档次(某些项指标派生类)。
譬如下边包车型大巴XML:

<?xml version="1.0" encoding="utf-8"?>
<XRoot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <List>
        <x1 aa="1" bb="2" />
        <x1 aa="3" bb="4" />
        <x2>
            <cc>ccccccccccc</cc>
            <dd>dddddddddddd</dd>
        </x2>
    </List>
</XRoot>

想像一下,下面那段XML是经过什么品种获得的呢?

答案如下(注意宝石蓝粗体部分):

public class XBase { }

[XmlType("x1")]
public class X1 : XBase
{
    [XmlAttribute("aa")]
    public int AA { get; set; }

    [XmlAttribute("bb")]
    public int BB { get; set; }
}

[XmlType("x2")]
public class X2 : XBase
{
    [XmlElement("cc")]
    public string CC { get; set; }

    [XmlElement("dd")]
    public string DD { get; set; }
}

public class XRoot
{
    [XmlArrayItem(typeof(X1)),
    XmlArrayItem(typeof(X2))]
    public List<XBase> List { get; set; }
}

系列化代码:

X1 x1a = new X1 { AA = 1, BB = 2 };
X1 x1b = new X1 { AA = 3, BB = 4 };
X2 x2 = new X2 { CC = "ccccccccccc", DD = "dddddddddddd" };
XRoot root = new XRoot { List = new List<XBase> { x1a, x1b, x2 } };

string xml = XmlHelper.XmlSerialize(root, Encoding.UTF8);
Console.WriteLine(xml);

小结:同时为列表成员钦点多个[XmlArrayItem(typeof(XXX))]可实现八种派生类型混在1块儿输出。

归来顶部

ca888会员登录,     数组和列表都在体系化时,默许情形下会基于项目中的数据成员名称改换1个节点,列表项会生成子节点,纵然要重命名,能够利用[XmlArrayItem]和[XmlArray]来促成。还是能一向用[XmlElement]调节不生成列表的父节点。 

类型定义与XML结构的炫丽

只若是1个新品类,小编肯定会大张旗鼓的运用类别化和反种类化的措施来行使XML, 但是,有时在维护二个老品种时,面对一群唯有XML却并未与之相应的C#项目时, 大家就供给凭借XML结构来逆向推导C#品类,然后技能运用类别化和反体系化的章程。 逆向推导的长河是劳动的,然则,类型推导出来之后,前边的专门的学问就回顾多了。

为了学会依据XML结构逆向推导类型,大家供给关爱一下类型定义与XML结构的映照关系。
在意:有时候大家也会思虑XML结构对于传输量及可阅读性的熏陶,所以关怀一下XML也是有必要的。

此处有一个XML文件,是笔者从Visual Sutdio的安装目录中找到的: ca888会员登录 9

<DynamicHelp xmlns="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd" 
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xsi:schemaLocation="http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd vsdh.xsd">
    <LinkGroup ID="sites" Title="Venus Sites" Priority="1500">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <LinkGroup ID="Venus Private Forums" Title="Venus Private Forums" Priority="1400">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <LinkGroup ID="ASP.NET Forums" Title="ASP.NET 1.0 Public Forums" Priority="1200">
        <Glyph Collapsed="3" Expanded="4"/>
    </LinkGroup>
    <Context>
        <Links>
            <LItem URL="http://www.asp.net/venus" LinkGroup="sites">Venus Home Page</LItem>
            <LItem URL="http://www.asp.net" LinkGroup="sites">ASP.NET Home Page</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=77" 
                    LinkGroup="Venus Private Forums">General Discussions</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=83" 
                    LinkGroup="Venus Private Forums">Feature Requests</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=78" 
                    LinkGroup="Venus Private Forums">Bug Reports</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=86" 
                    LinkGroup="Venus Private Forums">ASP.NET 2.0 Related issues</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=11" 
                    LinkGroup="ASP.NET Forums">Announcements</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=15" 
                    LinkGroup="ASP.NET Forums">Getting Started</LItem>
            <LItem URL="http://www.asp.net/Forums/ShowForum.aspx?tabindex=1&amp;ForumID=18" 
                    LinkGroup="ASP.NET Forums">Web Forms</LItem>
        </Links>
    </Context>
</DynamicHelp>

什么用反体系化的点子来读取它的多少吧,笔者在博客的最终将交由完整的兑今世码。
前日,大家照旧看一下以此XML有啥样特征吗。

<LinkGroup ID="sites" Title="Venus Sites" Priority="1500">

对于这一个节点的话,它富含了八个数据项(属性):ID,Title,Priority。 那样的LinkGroup节点有多少个。
看似的还有Glyph节点。

<LItem URL="http://www.asp.net" LinkGroup="sites">ASP.NET Home Page</LItem>

LItem节点除了与LinkGroup有着周围的数量(属性)之外,还包罗着三个字符串:ASP.NET Home Page , 那是其它1种多少的存放格局。

除此以外,LinkGroup和LItem都同意再现,我们得以用数组或然列表(Array,List)来掌握它们。

本人还发掘部分嵌套关系:LinkGroup能够涵盖Glyph,Context包括着Links,Links又饱含了多少个LItem。
甭管怎么嵌套,小编发觉数目都是带有在2个3个的XML节点中。

只要用规范的单词来描述它们,大家得以将ID,Title,Priority那多少个数据项称为 XmlAttribute, LItem,LinkGroup节点称为 XmlElement,”ASP.NET Home Page“出现的职责能够称作 InnerText。 基本上,XML就是由那三类数据整合。

上边我来演示怎样运用那两种多少项。

再次回到顶部

XML是一种很宽泛的数码保存方法,小编每每用它来保存一些数据,或然是一些布置参数。 使用C#,我们能够借助.net framework提供的大队人马API来读取只怕创设修改这一个XML, 但是,区别人利用XML的方法很有相当大可能率并分化样。 前些天自身希图谈谈自个儿利用XML的局地办法,供我们参考。

使用 XmlElement

第二,小编来定义三个档期的顺序:

public class Class1
{
    public int IntValue { get; set; }

    public string StrValue { get; set; }
}

下边是连串化与反类别的调用代码:

Class1 c1 = new Class1 { IntValue = 3, StrValue = "Fish Li" };
string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
Console.WriteLine(xml);

Console.WriteLine("---------------------------------------");

Class1 c2 = XmlHelper.XmlDeserialize<Class1>(xml, Encoding.UTF8);
Console.WriteLine("IntValue: "   c2.IntValue.ToString());
Console.WriteLine("StrValue: "   c2.StrValue);

运转结果如下:

<?xml version="1.0" encoding="utf-8"?>
<Class1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <IntValue>3</IntValue>
    <StrValue>Fish Li</StrValue>
</Class1>
---------------------------------------
IntValue: 3
StrValue: Fish Li

结果展现,IntValue和StrValue这么些属性生成了XmlElement。

小结:暗中同意情状下(不加任何Attribute),类型中的属性也许字段,都会生成XmlElement。

回到顶部

    • 重命名节点名称
  • 开始
  • 最简易的使用XML的法子
  • 类型定义与XML结构的投射
  • 使用 XmlElement
  • 使用 XmlAttribute
  • 使用 InnerText
  • 重命名节点名称
  • 列表和数组的系列化
  • 列表和数组的做为数据成员的系列化
  • 类型承接与反种类化
  • 反体系化的实战演习
  • 反系列化的行使总计
  • 扫除无需连串化的积极分子
  • 强制内定成员的体系化顺序
  • 自定义系列化行为
  • 体系化去掉XML命名空间及注脚头
  • XML的接纳建议

反体系化的实战演练

接下去,我们将基于前边介绍的知识点,用反连串化的措施来分析本文早先处贴出的那段XML: ca888会员登录 10;)

那段XML的根成分是DynamicHelp,因而,我们供给定义三个品类,类名叫DynamicHelp。 再观望这段XML,它应该包蕴1个LinkGroup列表,和二个Context属性,所以能够如此定义那三个项目:

public class DynamicHelp
{
    [XmlElement]
    public List<LinkGroup> Groups { get; set; }

    public Context Context { get; set; }
}

public class LinkGroup { }

public class Context { }

再来看LinkGroup,它涵盖五个数据成员,以及多少个子节点:Glyph,因而能够这么定义它们:

public class LinkGroup 
{
    [XmlAttribute]
    public string ID { get; set; }
    [XmlAttribute]
    public string Title { get; set; }
    [XmlAttribute]
    public int Priority { get; set; }

    public Glyph Glyph { get; set; }
}

public class Glyph
{
    [XmlAttribute]
    public int Collapsed { get; set; }
    [XmlAttribute]
    public int Expanded { get; set; }
}

LItem节点也大约,它就富含了U奥迪Q3L,LinkGroup和一个文本节点,由此得以那样定义它:

public class LItem
{
    [XmlAttribute]
    public string URL { get; set; }
    [XmlAttribute]
    public string URL { get; set; }

    [XmlText]
    public string Title { get; set; }
}

Context节点也不复杂,就只含有了3个LItem列表,由此得以这么定义它:

public class Context 
{
    public List<LItem> Links { get; set; }
}

好了,类型都定义好了,再来试试反种类化:

DynamicHelp help = XmlHelper.XmlDeserializeFromFile<DynamicHelp>("Links.xml", Encoding.UTF8);

foreach( LinkGroup group in help.Groups )
    Console.WriteLine("ID: {0}, Title: {1}, Priority: {2}, Collapsed: {3}, Expanded: {4}",
        group.ID, group.Title, group.Priority, group.Glyph.Collapsed, group.Glyph.Expanded);

foreach( LItem item in help.Context.Links )
    Console.WriteLine("URL: {0}, LinkGroup: {1}, Title: {2}",
        item.URL.Substring(0, 15), item.LinkGroup, item.Title);

显示器展现:

未处理的异常:  System.InvalidOperationException: XML 文档(4, 2)中有错误。 
---> System.InvalidOperationException: 不应有 
<DynamicHelp xmlns='http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd'>。

嗯,抛分外了。 别急,看看那些说怎么。 好像是在说命名空间不可能辨识。 依据分外的讲述,小编还要修改一下DynamicHelp的概念,改成这么:

[XmlRoot(Namespace = "http://msdn.microsoft.com/vsdata/xsd/vsdh.xsd")]
public class DynamicHelp

重复运转,结果如下:

ID: sites, Title: Venus Sites, Priority: 1500, Collapsed: 3, Expanded: 4
ID: Venus Private Forums, Title: Venus Private Forums, Priority: 1400, Collapsed: 3, Expanded: 4
ID: ASP.NET Forums, Title: ASP.NET 1.0 Public Forums, Priority: 1200, Collapsed: 3, Expanded: 4
URL: http://www.asp., LinkGroup: sites, Title: Venus Home Page
URL: http://www.asp., LinkGroup: sites, Title: ASP.NET Home Page
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: General Discussions
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: Feature Requests
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: Bug Reports
URL: http://www.asp., LinkGroup: Venus Private Forums, Title: ASP.NET 2.0 Related issues
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Announcements
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Getting Started
URL: http://www.asp., LinkGroup: ASP.NET Forums, Title: Web Forms

总计:依据XML结构推导类型时,要保障项指标档期的顺序结构与XML相称, 数据的寄放方式能够透过[XmlElement],[XmlAttribute],[XmlText]艺术来提议。

回来顶部

回去顶部

public class Root
{
    public Class3 Class3 { get; set; }
    [XmlArrayItem("c2")]
    [XmlArray("cccccccccccc")]
    public List<Class2> List { get; set; }
}
public class Root
{
    public Class3 Class3 { get; set; }
    [XmlElement("c2")]
    public List<Class2> List { get; set; }
}

版权声明:本文由ca888发布于编程程序,转载请注明出处:深度解析XML的组织与类映射