文章教程

11.5XML

8/31/2020 9:56:04 PM 人评论 次浏览

图片 1 知识点讲解:光盘:视频\PPT讲解(知识点)\第11章\XML.mp4

XML译为可扩展标记语言,是网络应用开发的一项新技术。XML同HTML一样,是一种标记语言,但是XML的数据描述能力要比HTML强很多,XML具有描述所有已知和未知数据的能力。XML可以为新的数据类型制定新的数据描述规则,作为对标记集的扩展。

XML具有以下特点。

  • XML数据可以跨平台使用并可以被阅读理解。
  • XML数据的内容和结构有明确的定义。
  • XML数据的内容和数据的表现形式分离。
  • XML使用的结构是开放的、可扩展的。

在ASP.NET开发体系中,XML可以作为数据资源的形式存在于服务器端,XML还可以作为服务器端与客户端的数据交换语言。并且在.NET框架中,提供了一系列应用程序接口来实现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文档都要包括至少一个根元素。根标记必须是非空标记,包括整个文档的数据内容。数据内容是位于标记之间的内容。

文档类型定义(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之间是逻辑或的关系

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>

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();

通过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的行为

教程类别