11.5 XML
知识点讲解:光盘:视频\PPT讲解(知识点)\第11章\XML.mp4
XML译为可扩展标记语言,是网络应用开发的一项新技术。XML同HTML一样,是一种标记语言,但是XML的数据描述能力要比HTML强很多,XML具有描述所有已知和未知数据的能力。XML可以为新的数据类型制定新的数据描述规则,作为对标记集的扩展。
XML具有以下特点。
- XML数据可以跨平台使用并可以被阅读理解。
- XML数据的内容和结构有明确的定义。
- XML数据的内容和数据的表现形式分离。
- XML使用的结构是开放的、可扩展的。
在ASP.NET开发体系中,XML可以作为数据资源的形式存在于服务器端,XML还可以作为服务器端与客户端的数据交换语言。并且在.NET框架中,提供了一系列应用程序接口来实现XML数据的读写。
11.5.1 XML概述
关于XML的知识有很多,但由于本书并不是专门介绍XML的,基于篇幅的限制,本节仅简要介绍一下XML的相关知识,使读者对XML有一个初步的了解。
XML语言对格式有严格的要求,主要包括格式良好和有效性两种要求。格式良好有利于XML文档被正确地分析和处理,大大提高XML的处理程序、处理XML数据的正确性和效率。XML文档满足格式良好的要求后,会对文档进行有效性确认。有效性是通过对DTD或Schema的分析判断的。一个XML文档由如下3部分组成。
1.XML声明
XML的声明格式如下。
<?xml version="1.0" encoding="GB2312"?>
XML标准规定,其声明必须放在文档的第一行。
2.处理指令PI
处理指令PI能够为处理XML的应用程序提供信息,其语法格式如下。
<? 处理指令名 处理指令信息?>
3.XML元素
元素是组成XML文档的核心,其语法格式如下。
<标记>内容</标记>
XML语法规定每个XML文档都要包括至少一个根元素。根标记必须是非空标记,包括整个文档的数据内容。数据内容是位于标记之间的内容。
11.5.2 文档类型定义
文档类型定义(DTD)是一种规范,在DTD中可以向XML的语法分析器解释XML文档标记集中每一个标记的含义。为此,要求DTD必须包含所有将要使用的词汇列表,否则XML解析器无法根据DTD验证文档的有效性。
DTD根据其出现的位置,可以分为内部DTD和外部DTD两种。内部DTD是指DTD和相应的XML文档处在同一个文档中;外部DTD就是DTD与XML文档处在不同的文档中。
例如在下面的代码中,包含了内部DTD的XML文档。
<?xml version="1.0" encoding="gb2312" standalone="yes"?>
<!DOCTYPE DocumentElement [
<!ELEMENT DocumentElement ANY>
<!ELEMENT basic (ID,NAME,CITY,PHONE,CARRIER,POSITION)>
<!ELEMENT ID (#|PCDATA)>
<!ELEMENT NAME (#|PCDATA)>
<!ELEMENT CITY (#|PCDATA)>
<!ELEMENT PHONE (#|PCDATA)>
<!ELEMENT CARRIER (#|PCDATA)>
<!ELEMENT POSITION (#|PCDATA)>
]>
<?xml-stylesheet type="text/xsl" href="style.xsl"?>
<DocumentElement>
<basic>
<ID>1</ID>
<NAME>张三</NAME>
<CITY>北京</CITY>
<PHONE>01012345678</PHONE>
<CARRIER>经理</CARRIER>
<POSITION>市场部经理</POSITION>
</basic>
</DocumentElement>
从以上代码中可以看出,描述DTD文档也需要一套语法结构,关键字是组成语法结构的基础。DTD的常用关键字信息如表11-22所示。
表11-22 DTD的常用关键字信息
关 键 字 |
说 明 |
---|---|
ANY |
数据既可以是纯文本,也可以是子元素,多用来修饰根元素 |
ATTLIST |
定义元素的属性 |
DOCTYPE |
描述根元素 |
ELEMENT |
描述所有子元素 |
EMPTY |
空元素 |
SYSTEM |
表示使用外部DTD文档 |
#FIXED |
表示ATTLIST定义的属性的值是固定的 |
#IMPLIED |
标识ATTLIST定义的属性不是必须赋值的 |
#PCDATA |
数据为纯文本 |
#REQUIRED |
ATTLIST定义的属性是必须赋值的 |
INCLUDE |
表示包括的内容有效,类似于条件编译 |
IGNORE |
与INCLUDE相应,表示包括的内容无效 |
DTD还提供了一些运算表达式来描述XML文档中的元素,具体信息如表11-23所示。
表11-23 运算表达式
运算表达式 |
说 明 |
---|---|
A+ |
元素A至少出现一次 |
A* |
元素A可以出现很多次,也可以不出现 |
A? |
元素A出现一次或不出现 |
(A B C) |
元素A、B、C的间隔是空格,表示它们是无序排列 |
(A,B,C) |
元素A、B、C的间隔是逗号,表示它们是有序排列 |
A|B |
元素A、B之间是逻辑或的关系 |
11.5.3 创建XML文件
XML语言仅仅是一种信息交换的载体,是一种信息交换的方法。如果要使用XML文档,则必须通过使用一种称为接口的技术。正如使用ODBC接口访问数据库一样,使用DOM接口应用程序使对XML文档的访问变得简单。
DOM是一个程序接口,应用程序和脚本可以通过这个接口访问和修改XML文档数据。DOM接口定义了一系列对象来实现对XML文档数据的访问和修改。DOM接口将XML文档转换为树形的文档结构,应用程序通过树形文档对XML文档进行层次化的访问,从而实现对XML文档的操作。例如,访问树的节点,创建新节点等。
微软的.NET框架实现了对DOM规范的良好支持,并提供了一些扩展技术,使得程序员对XML文档的处理更加简便。而基于.NET框架的ASP.NET可以充分使用.NET类库来实现对DOM的支持。
.NET类库中支持DOM的类主要存在于System.Xml和System.Xml.XmlDocument命名空间中。这些类分为两个层次:基础类和扩展类。基础类包括用来编写操纵XML文档的应用程序所需要的类;扩展类被定义用来简化程序员的开发工作的类。
基础类包含如下3个类。
- XmlNode类:用于表示文档树中的单个节点,它描述了XML文档中各种具体节点类型的共性。它是一个抽象类,在扩展类层次中有它的具体实现。
- XmlNodeList类:用于表示一个节点的有序集合,它提供了对迭代操作和索引器的支持。
- XmlNamedNodeMap类:用于表示一个节点的集合。该集合中的元素可以使用节点名或索引来访问,支持使用节点名称和迭代器对属性集合的访问,并且包含对命名空间的支持。
扩展类中包括由XmlNode类派生出来的类,具体如表11-24所示。
表11-24 扩展类中包含的类
类 |
说 明 |
---|---|
XmlAttribute |
表示一个属性,此属性的有效值和默认值在DTD或架构中进行定义 |
XmlAttributeCollection |
表示属性集合,这些属性的有效值和默认值在DTD或架构中进行定义 |
XmlComment |
表示XML文档中的注释内容 |
XmlDocument |
表示XML文档 |
XmlDocumentType |
表示XML文档的DOCTYPE声明节点 |
XmlElement |
表示一个元素 |
XmlEntity |
表示XML文档中一个解析过或未解析过的实体 |
XmlEntityReference |
表示一个实体的引用 |
XmlLinkedNode |
获取紧靠该节点(之前或之后)的节点 |
XmlReader |
表示提供对XML数据进行快速、非缓存、只进访问的读取器 |
XmlText |
表示元素或属性的文本内容 |
XmlTextReader |
表示提供对XML数据进行快速、非缓存、只进访问的读取器 |
XmlTextWriter |
表示提供快速、非缓存、只进方法的编写器,该方法生成包含XML数据[这些数据符合W3C可扩展标记语言(XML)1.0和XML中命名空间的建议]的流或文件 |
XmlWriter |
表示提供快速、非缓存和只进方法的编写器,该方法生成包含XML数据 |
1.创建XML文档
在ASP.NET中,有如下两种创建XML文档(XMLDocument)的方法。
- 创建不带参数的XML文档
例如,下面的代码创建了一个不带参数的XML文档。
XmlDocument doc = new XmlDocument();
创建文档后,可通过Load方法从字符串、流、URL、文本读取器或XmlReader派生类中加载数据到该文档中。另外,也可以使用LoadXML方法加载。此方法从字符串中读取XML。
- 创建带参数的XML文档
通常是创建一个XML文档后,将XmlNameTable作为参数传递给它。XmlNameTable类是原子化字符串对象的表。该表为XML分析器提供了一种高效的方法,即对XML文档中所有重复的元素和属性名使用相同的字符串对象。创建XML文档时,将自动创建XmlNameTable,并在加载此文档时用属性和元素名加载XmlNameTable。
如果已经有一个包含名称表的文档,并且这些名称在另一个文档中会很有用,则可使用将XmlNameTable作为参数的Load方法创建一个新文档。使用此方法创建文档后,该文档使用现有XmlNameTable。该XmlNameTable包含所有已从其他文档加载到此文档中的属性和元素,可用于有效地比较元素和属性名。例如,下面的代码创建了带参数的XML文档实例。
System.Xml.XmlDocument doc = new XmlDocument(xmlNameTable);
2.读入文档
XML信息可以从不同的格式读入内存,读取源包括字符串、流、URL、文本读取器或XmlReader的派生类。Load方法可以将文档置入内存中。另外,LoadXML方法可以从字符串中读取XML。
请看下面的一段代码。
XmlDocument doc = new XmlDocument(); // 创建文档
doc.LoadXml(" <basic>" +
"<ID>1</ID>" +
"<NAME>C罗</NAME>" +
"<CITY>鲁尼</CITY>" +
"<PHONE>11111111</PHONE>" +
"<CARRIER>攻击手</CARRIER>" +
"<POSITION>曼联</POSITION>" +
"</basic>");
doc.Save("123.xml"); //把文档保存到一个文件中
在上面的代码中,使用LoadXML方法加载了XML,然后将数据保存到一个名为“123.xml”的文本文件中。
3.创建新节点
XMLDocument中的Create方法用于所有节点类型,可以为该方法提供名称以及那些具有内容节点的内容或其他参数。XMLDocument中常用的创建节点的方法信息如表11-25所示。
表11-25 XMLDocument创建节点的方法信息
方 法 |
说 明 |
---|---|
CreateAttribute |
创建具有指定名称的XmlAttribute |
CreateCDataSection |
创建包含指定数据的XmlCDataSection |
CreateComment |
创建包含指定数据的XmlComment |
CreateDocumentType |
返回新的XmlDocumentType对象 |
CreateElement |
创建XmlElement |
CreateEntityReference |
创建具有指定名称的XmlEntityReference |
CreateNode |
创建XmlNode |
CreateTextNode |
创建具有指定文本的XmlText |
创建新节点后,可以使用专用方法将其插入到XML结构树中。各方法的具体信息如表11-26所示。
表11-26 将节点插入到XML结构树中的方法
方 法 |
说 明 |
---|---|
InsertBefore |
插入到引用节点之前 |
InsertAfter |
插入到引用节点之后 |
AppendChild |
将节点添加到给定节点的子节点列表的末尾 |
PrependChild |
将节点添加到给定节点的子节点列表的开头 |
Append |
将 XmlAttribute 节点追加到与元素关联的属性集合的末尾 |
4.修改XML文档
在.NET框架下,用户通过DOM可以用多种方法来修改XML文档的节点、内容和值。其中常用的修改XML文档的方法有如下几种。
- 使用XmlNode.Value方法更改节点值。
- 通过用新节点替换现有节点来修改全部节点集。这可以使用XmlNode.InnerXml属性完成。
- 通过XmlNode.ReplaceChild方法用新节点替换现有节点。
- 使用XmlCharacterData.AppendData方法、XmlCharacterData.InsertData方法或XmlCharacter Data.ReplaceData方法将附加字符添加到从XmlCharacter类继承的节点。
- 对从XmlCharacterData继承的节点类型使用DeleteData方法移除某个范围的字符来修改内容。
- 使用SetAttribute方法更新属性值。如果不存在属性,则SetAttribute将创建一个新属性;如果存在属性,则更新属性值。
5.删除XML文档的节点、属性和内容
DOM在内存中之后,可以删除树中的节点,或删除特定节点类型中的内容和值。
- 删除节点
如果要从DOM中删除一个节点,可以使用RemoveChild方法来删除特定的节点。在删除节点时,此方法删除属于所删除的节点的子树。
如果要从DOM中删除多个节点,可以使用RemoveAll方法删除当前节点的所有子级和属性。
如果使用XmlNamedNodeMap,则可以使用RemoveNamedItem方法删除节点。
- 删除属性集合中的属性
通常使用XmlAttributeCollection.Remove方法来删除特定属性。另外,也可以使用方法XmlAttributeCollection.RemoveAll来删除集合中的所有属性,使元素不具有任何属性;或者使用方法XmlAttributeCollection.RemoveAt移除属性集合中的属性。
- 删除节点属性
通常使用XmlElement.RemoveAllAttributes方法删除属性集合;使用XmlElement.Remove Attribute方法按名称删除集合中的单个属性;使用XmlElement.RemoveAttributeAt方法按索引号来删除集合中的单个属性。
- 删除节点内容
通常使用DeleteData方法删除字符。此方法从节点中移除某个范围的字符。如果要完全移除内容,则移除包含此内容的节点。如果要保留节点,但节点内容不正确,则修改内容。
6.保存XML文档
可以使用Save方法保存XML文档,Save方法含有如下4个重载方法。
- Save(string filename):将文档保存到文件filename的位置。
- Save(System.IO.Stream outStream):保存到流outStream中,流的概念存在于文件操作中。
- Save(System.IO.TextWriter writer):保存到TextWriter中。TextWriter也是文件操作中的一个类。
- Save(XmlWriter w):保存到XmlWriter中。
7.使用XPath导航选择节点
DOM包含的方法允许使用XPath导航查询DOM中的信息。可以使用XPath查找单个特定节点,并且只使用一行XPath代码即可实现。
DOM类提供两种XPath选择方法。SelectSingleNode方法返回符合选择条件的第一个节点,SelectNodes方法返回包含匹配节点的XmlNodeList。
例如在下面的代码中,通过使用XPath从一个名为doc的XmlDocument中,查询出了所有的“lihai”节点信息。
XmlDocument doc = new XmlDocument(); //创建DOM
doc.Load("123.xml"); //把XML文档装入DOM
XmlNodeList nodeList; //定义节点列表
XmlNode root = doc.DocumentElement; //定义根节点,并把DOM的根节点赋给它
nodeList=root.SelectNodes("//lihai "); //查找basic节点列表
//循环访问节点列表,并做一些修改
foreach (XmlNode basic in nodeList)
{
basic.LastChild.InnerText="无职称"; //修改最后一个子节点内容
}
doc.Save("1231xml"); //保存DOM
其中123.xml文档如下所示。
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<lihai>
<ID>1</ID>
<NAME>鲁尼</NAME>
<CITY>曼联</CITY>
<PHONE>11111111</PHONE>
<CARRIER>前锋</CARRIER>
<POSITION>21</POSITION>
</lihai>
</DocumentElement>
11.5.4 DataSet读取XML数据
DataSet对象可以使用GetXml方法将数据导出为一个XML字符串,使用GetXmlSchema方法将数据的组织模式导出为一个XML Schema字符串。例如下面的代码。
DataSet dataSet = new DataSet();
//执行一些操作为DataSet对象填充数据,此处代码省略
string xmlString = dataSet.GetXml(); //导出数据为XML格式
string xmlSchema = dataSet.GetXmlSchema(); //导出数据的组织形式
另外,DataSet还可以使用方法WriteXml和WriteXmlSchema,把DataSet对象中的数据和Schema以XML的形式写出。例如下面的代码。
//写出XML数据
DataSet dataSet = new DataSet();
//执行一些操作为DataSet对象填充数据,此处代码省略
System.IO.FileStream fs = new System.IO.FileStream("basic1.xml", System.IO.FileMode.Create);
dataSet.WriteXml(fs);
fs.Close();
//写出数据组织形式
DataSet dataSet = new DataSet();
//执行一些操作为DataSet对象填充数据,此处代码省略
System.IO.FileStream fs2 = new System.IO.FileStream("basic2.xml",System.IO.FileMode.Create);
dataSet.WriteXmlSchema(fs2);
fs2.Close();
11.5.5 XML填充DataSet
通过DataSet对象中的ReadXmlSchema方法,可以利用已存在的XML Schema建立数据模式。ReadXmlSchema方法包含多种重载版本,具体如下。
- ReadXmlSchema(string fileName):从指定的文件读取XML Schema。
- ReadXmlSchema(System.IO.Stream stream):从流中读取XML Schema。
- ReadXmlSchema(System.IO.TextReader reader):读取存在于TextReader的XML Schema。
- ReadXmlSchema(XmlReader reader):读取存在于XmlReader的XML Schema。
例如下面的一段代码。
//使用文件名
DataSet dataSet = new DataSet();
dataSet.ReadXmlSchema(Server.MapPath("basic.xml"));
//使用流对象
DataSet dataSet = new DataSet();
System.IO.FileStream fs = new System.IO.FileStream("basic.xml", System.IO.FileMode.Open);
dataSet.ReadXmlSchema(fs);
s.Close();
//使用TextReader
DataSet dataSet = new DataSet();
//这里StreamReader是TextReader的派生类
System.IO.StreamReader streamReader = new System.IO.StreamReader(Server.MapPath("basic.xml"));
dataSet.ReadXmlSchema(streamReader);
streamReader.Close();
//使用XmlReader
DataSet dataSet = new DataSet();
//这里XmlTextReader是XmlReader的派生类
System.IO.FileStream fs = new System.IO.FileStream("basic.xml", System.IO.FileMode.Open);
System.Xml.XmlTextReader xmlReader = new XmlTextReader(fs);
dataSet.ReadXmlSchema(xmlReader);
xmlReader.Close();
在上述代码中,通过使用ReadXmlSchema方法读取了XML Schema。另外,DataSet对象还可以使用ReadXml方法读取XML文件或流。ReadXml方法对于每一种XML数据来源(流、文件、TextReader和XmlReader),都提供了如下2种形式的重载函数。
- 仅包含一个指定XML数据来源的参数。
- 包含指定XML数据来源的参数和指定读取数据时生成数据模式Schema的行为