XML概述

XML概述

 

首先说一下,这一部分咱们重点讲解一下关于在.NET中操作XML,前面好像说过关于LINQ to XML,不知打你们还记得多少?反正楼主是一点都不记得了.哈哈

 

今天学的知识是为了什么?为了明天的荒废...

 

这是韩寒说的!

 

韩寒说的对啊!

 

这句话是我说的!!!

 

为啥要有XML?

 

XML----可扩展标记语言.通过名字完全不明白XML是个啥玩意.实际上不用关心XML的名字,你需要明白的是XML是用来干啥的就好.在学一门新东西的时候,你需要问自己三个问题:它是啥?它有啥用?我为啥要学它?

 

XML的主要用途是用来描述和交换数据的.

 

先从XML的一个应用说起:应用程序配置文件.应用程序经常需要一些参数,而这些参数与本地计算机的运行环境或用户设置有关.因此,为了方便对应用程序进行部署,需要将这些参数保存在配置文件中供应用程序读取或写入,使得应用程序在部署后不需要重新编译,只需要修改配置文件中的参数就可.常见的配置参数有数据库连接字符串,网络IP和端口设置,日志保存路径等..NET应用程序中,这些配置通常保存在一个后缀名为.config的文件中,使用记事本打开应该能看出来是一个标准的XML文件.

 

所以,应用程序配置文件的作用是描述程序外部的参数信息,并供应用程序所用.

 

在以前还没有XML的时候,一般是使用纯文本来保存配置信息的,比如新建一个config.txtconfig.ini文件(只是后缀不同),然后将这些信息以”key-value”的方式保存起来,例如:

ConnectionString=Data Source=Syx--PC;Initial Catalog=TestDB;User ID=sa;pwd=123456
IP=192.168.3.19
port=8080
LogFolder=D:\LogFiles

 

使用以上的方式进行保存有这么几个问题:

1.)结构散乱,如果要配置多个连接字符串或者多个TCP端口,文件结构就会变成这样了:

ConnectionString1=...

ConnectionString2=...

IP1=...

Port1=...

IP2=...

Port2=...

2.)读取不方便.如果要读取IP2的值,需要逐行读取,并判断”=”的左边是否是IP2,如果是,”=”右边的值.

3.)写入不方便.如果在ConnectionString2后面多添加一个ConnectionString3,那么就会非常麻烦.

4.)读写配置文件的API需要自行编号.

 

 

大家应该多多少少的了解过HTML或者XHTML,为了解决上面的问题,我们就引入了类似HTML的标记语法来重新编写配置文件.对于上面的案例:

 

<ConnectionStrings>
<ConnectionString name=”SQLLite”>...</ConnectionString>
<ConnectionString name=”MySql”>...</ConnectionString>
<ConnectionString name=”MSSQL”>...</ConnectionString>
</ConnectionStrings>
<TCPSettings>
<ip port=”8001”>192.168.3.3</ip>
<ip port=”8002”>192.168.3.2</ip>
<ip port=”8003”>192.168.3.1</ip>
</TCPSettings>


 

 

HTML,标记(tag)是关注结构和表现得,而非语义的.例如,<p>...</p>是关注结构的,说明这是一个段落,但是没有说明标记之间是啥内容;<b>...</b>是关注表现得,说明标记之间的字体应该加粗,没说标记之间是啥内容.对于本例的配置文件来说,标记是关注语义的,它本身也具有含义,说明了标记之间包含的是什么内容.例如<TCPSettings/>,说明了标记内是关于TCP的设置.

 

我们不提倡HTML中使用关注表现的标记,例如<font/>,<center/>,<b/>,表现应该有CSS去完成.

 

上面咱们自创了一个配置文件,这个文件就是”XML文档”.XMLHTML不同的是:XML没有任何自己的标记,完全由开发者定义标记.

 

但是XML也是需要符合规则的.这些规则不多,只要符合了这些规则开发者就可以自由发挥和创作了.

 

对于HTML来说,不仅规则是固定了,标记也是固定的,不能使用自定义的标记. XML是一组规则,HTML是基于这组规则的一个应用,适用于描述Web页面,SVGXML的另一个应用,适用于描述适量图形.

 

本例中定义的标记<TCPSettings>,从地位上来所,HTML,SVG是一样的,只不过是属于我们独立的应用,应用于描述应用程序配置.

 

HTMLXHTML的最重要的区别是XHTML符合XML的规则,但是HTML不完全符合.

 

可能会有人问,如果采用了这种XML的写法貌似对采用纯文本的”key-value”还麻烦,别急,我们采用XML的最主要的原因是我们有一套关于操作XMLAPI.我们通常有以下几种处理方式:

(1).类似ADO.NET中的DataSet,一次性将数据全部读取到DataSet,然后便可以对DataSet中任意位置的数据进行读取,修改,删除,写入.我们也可以创建一个List<string>用来保存文档内容,先使用StreamReader读取配置文件的每一行,然后添加至List<string>,最后guanbiStreamReader.采用这种方式的特点:在得到List<string>之后,可以使用索引访问List<string>的任意位置,但因为整个文档分成分成行存放在了List<string>,会比较占用内存.


(2).类似ADO.NET中的DbDataReader,采用单向,只读的方式逐行读取,读取一行的处理一行,从文档头读取到文档末尾.此时,虽然同样是使用StreamReader,但只需要一个string变量保存读取的一行,然后对它进行处理.采用这种方式的特点是:快速,集合不占用什么内存.这种湖区数据的模式也叫做拉模式.


(3).(2)类似,但使用事件注册,通知机制,即采用推模式(push).由读取文档的类型发布事件,没读到一行,就将读到的数据推给注册事件的客户端对象或程序.

 

现在读写配置文件的需要很普遍,几乎所有的应用程序都需要用到,所以有一套规范,关于这套规范你自己在网上搜搜吧,我不写了.

 

注意:C#,属性的英文是Property,Attribute通常翻译为特性.但在XML,属性的英文是Attribute.

 

 

与上面三种方式类似的是XML的处理模型

 

1.XML DOM队里XML文档的方式和前面的1类似,只不过,它不是用List<string>XML文档分成多个行来保存,而是将XML文档呈现为一个节点树.XML DOM处理XML文档的特点和1也是一样的,可以访问任意节点,可以对节点增删改查,但是需要的内存较大.

 

2.XmlReaderXmlWrite

 

.NET中提供了System.Xml.XmlReaderSystem.Xml.XmlWriter两个基础类型用于单向的,只读/只写的操作.这两个类型的操作方式和前面的2是类似的.区别是StreamReader是逐行读取,XmlReader针对于XML的树形结构,是逐节点读取.

 

3.SAX

 

SAX是用于XML文档的事件驱动的推模式,和前面的3类似.虽然不是W3c的标准,但是是一个被广泛认可的API,SAX的缺点是会推送所有的数据过来,不论是需要还是不需要的,因此要在事件处理程序中进行筛选和处理..NET中没有对SAX提供支持,但是尅通过包装XmlReader模拟出和SAX一样的效果.

 

 

XML验证----XSD,DTDXDR

 

XML标准定义了什么样的XML是格式良好的,但是它不一定是有效的.前面说了XML的存储作用,现在来说下XML的另一个作用----交换数据.

 

假设开发了一个基于XML的影片资料库程序,它可以接受各个影院发来的新近上映的电影信息的XML文档.程序在接受XML文档之后,可以读取其中的数据,然后进行处理,比如存入中心数据库.对于影片数据库,它接受的XML格式为:

<?xml version="1.0" encoding="utf-8" ?>
<movieList>
  <moive>
    <title>影片名</title>
    <director>导演</director>
<starring>主演</starring>
<genre>类型</genre>
    <releaseDate>上映日期</releaseDate>
  </moive>
  <movie>
    ...
  </movie>
</movieList>


 

显然上面的XML格式是正确的,但它不一定是有效的.啥意思?XML的结构良好与文档有效的关系类似于C#中语法正确(编译通过),但运行时报错.比如这样的语句:

int index=Convert.ToInt32(“abcd”);


从语法上来说,没问题,但是在运行时,就会报错,因为字符串abcd无法转换为int类型.

 

XML文档也是类似的,尽管结构正确.但对于元素releaseDate来说,可以接受的文本是日期了日行,例如2012-2-2;对于元素genre来说,可以接受的可能是一个枚举,如果没有东西来约束,所有元素的文本,属性的值,都会视为字符串类型.因此,影院实际发来的XML文档,可能与应用程序所期望的不完全一致,比方说,releaseDate的文本为”March 13,2012”.甚至,影院可能会自作主张,修改XML的文档结构,XML多添加一个元素,比如nation(国家);或者,starring元素扩展为树形结构,比如:

<starring>
  <actor>主演A</actor>
  <actor>主演B</actor>
  <actor>主演C</actor>
</starring>


 

解决这个问题大致有三种方式:

(1).将影院管理程序所期望的XML格式写成一份说明书(例如,”影片XL文档结构说明.doc”),然后发给各个影院,要求他们按扎个说明书来生成XML文档.但影院是否照做就是另外一回事了.


(2).XML的数据处理 程序中朱哥去检查XML的文档结构,每一个元素,属性的值是否正确.这将很麻烦,而且耦合性太高:应用程序本身应有的主要逻辑----获取并处理数据和校验XML结构是否正确,内容是否合法耦合在了一起.


(3).编写一个文档,该文档定义了XML文档的结构,标记,属性,属性值,文本值等一切信息,相当于XML文档的”元数据”.并且,该文档可以由程序进行处理,对目标XML进行验证.有了这个文档之后,就可以在程序中将校验XML文档结构和处理数据的逻辑分离开来,即松耦合.

 

 

第三种方式是最好的,为啥?这种定义了XML的结构和内容,用于验证XML有效性的文档,XML一样,也制定成了标准或者规范,分别是XSD,DTDXDR.他们和XML文档的关系如下 :

 

 

提示:如果设计的XML仅仅是为了自己使用,比方应用程序配置,或者数据存储(将对象序列化为XML进行保存),不存在与第三方进行数据交换,那么,是不需要进行有效性验证的,因为我们没有必要自讨苦处,写入明知道非法的数据.

 

关于XSD,DTD,XDR的内容如果感兴趣自己去百度吧.

 

 

XML格式转换----XSLT

 

XSLT的作用是将一种格式的XML转换为另一种.通常,我们设计的XML文档只适用于某一特定领域,而如果想要应用于另一领域,则需要进行转换.以影片信息威力,假设另一家公司也需要影片信息,并且也采用XML格式接受数据,但是他们所需要的XML格式与我们定义的完全不同,采用的办法就是XSLT,它也是用XML来描述的.这种关系如下:

 

类似的,要想将影片信息系那是在浏览器中,由于浏览器领域所接受的格式为HTML,因此,也可以使用XSLTXML转换为HTML格式.关系和上图一样

 

 

 

XML选择器----XPATH

前面说过采用List<string>来保存XML文档时,如果想访问它的任意一样,可以使用索引,例如list[2].当采用XML DOM,XML呈现为一棵节点树,System.Xml.XmlDocument类型表示.那么如何访问XmlDocument中的任意节点?类似于CSS中的选择器,选取XML中的任意节点,可以使用XPATH.

 

不知道大家还记得CSS选择器吗?语句body{font-size:14px},选择了页面中的body元素,并设置css样式font-size14px;语句dic.centent p{text-indent:2em;},选择了页面中的所有clas属性为contentdic下的p元素,并设置css样式text-indent2em.

 

CSS选择器类似,XPATH的规则也很多,但常用的就几个,如下表所示:


表达式

                   描述

/

以根节点为绝对路径选择子节点

/movieList/movie/starring(选择了所有父元素为movie,祖父元素为movieListstarring元素,并且movieList是根元素)

//

以相对路径选择所有的子节点

//movie/starring(选择所有父元素为moviestarring元素,不考虑它们在文档中的位置)

nodename

从当前节点下,选择名称为”nodename”的子节点

movie(选择了当前节点下名称为movie的子元素)

.

选择当前节点

..

选择当前节点的父节点

*

选择所有节点

@

选择属性

//movie/@id(选择了所有movie元素的id属性)

[]

定义选择条件

//movie[id=”1”](选择了所有id1movie元素)

[index]

根据位置选择元素

//movie[1](选择了第一个movie元素)

 

说实话,关于XML的相关概念楼主本来不想说的,本来想直接进入所操作XML的部分,但是楼主思前想后觉得有些东西还是按部就班的来吧,毕竟咱们和培训班的学生有差别,具体差别是啥我不说,你也明白.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值