读取XML数据只是完成了工作的一半。如果您是一位开发人员并且需要从第三方供应商那里获取XML数据并根据定制的DTD或者XML模式将这些数据转换成一个新的XML文件,您将会怎么办?您该如何完成这个任务呢?可以自由地写入XML文件吗?幸运的是,就像有一个使用只读、只向前方式读取XML数据的类一样,.NET Framework也提供了一个以快速、非缓存、只向前的方式动态写入XML数据的类,即XmlWriter类。完全可以将XmlWriter对象理解为XmlReader对象的对等对象。
使用XmlWriter写入XML数据
如果您对XML有所了解,那么可能会知道W3C提出的XML 1.0规范描述了XML的串行化形式—— 当作为文本生成时XML出现的方式—— 包括尖括号、开始标签和结束标签以及命名空间和XML声明。如果您已经获得了需要写入XML的数据,那么手动执行将不会很困难,但是.NET Framework提供了XmlWriter类来帮助您完成大量的格式化工作,如跟踪缩排和在任意地方插入命名空间信息。您可以利用XmlWriter类来建立符合W3C可扩展标记语言XML 1.0 Second Edition(www.w3.org/TR/2000/REC-xml-20001006.html)推荐标准和XML命名空间推荐标准(www.w3.org/TR/REC-xml-names/)的XML文档。表4-6列出了XmlWriter对象提供的重要属性。
表4-6 XmlWriter类的重要属性
属 性 |
说 明 |
Settings |
返回用于创建XmlWriter对象实例的XmlWriterSettings对象 |
WriteState |
以WriteState枚举的形式返回书写器的状态 |
XmlLang |
获得当前的xml:lang范围;xml:lang属性为作者提供了一种可靠的方法,以区别包含在特定文档中的特定语言 |
XmlSpace |
以XmlSpace对象的形式获得当前xml:space的范围;xml:space属性允许元素向应用程序声明它们的空白是否有意义 |
表4-7显示了XmlWriter对象的一些最常用的方法。
表4-7 XmlWriter类的重要方法
方 法 |
说 明 |
Close |
关闭当前流和底层流 |
Create |
创建和返回XmlWriter对象的一个实例 |
WriteAttributes |
写出在XmlReader对象中当前位置上找到的所有属性 |
WriteAttributeString |
以指定值写入属性 |
WriteBase64 |
以base64对指定的二进制字节进行编码并写出结果文本 |
WriteCData |
写出包含指定文本的CData区域 |
WriteCharEntity |
以十六进制字符实体引用格式写出Unicode字符 |
WriteChars |
用于一次在一个缓冲中写入大量文本 |
WriteComment |
写出包含指定文本的XmlComment |
WriteDocType |
用指定的名称和可选的属性写出DOCTYPE声明 |
WriteElementString |
写入一个包含指定字符串值的元素 |
WriteEndAttribute |
关闭由XmlWriter初始化的前一个WriteStartAttribute方法调用 |
WriteEndDocument |
关闭所有打开的元素和属性并将书写器设回开始状态 |
WriteEndElement |
关闭由XmlWriter的WriteStartElement方法创建并打开的元素;如果该元素没有包含内容,这写入一个短结束标签“/>”;否则,将写入一个完整的结束标签 |
WriteEntityRef |
写出一个实体引用 |
WriteFullEndElement |
关闭打开的元素。这个方法与WriteEndElement方法的不同之处在于当要写入空元素时是否可见。这个方法通过写入完整的结束标签总是会关闭打开的标签,并特别用于在写入用于嵌入HTML脚本代码块的标签 |
WriteName |
写出指定的名称 |
WriteNode |
从源对象中复制所有内容至当前的书写器实例 |
(续表)
方 法 |
说 明 |
WriteProcessingInstructioin |
在名称和文本之间写出一个处理指令 |
WriteQualifiedName |
通过在给定的命名空间范围内查找前缀名来写出命名空间限定的 名称 |
WriteRaw |
不检查内容而手动写出原始标记 |
WriteStartAttribute |
写入属性的开始 |
WriteStartDocument |
写入XML声明 |
WriteStartElement |
写出指定的开始标签 |
WriteString |
写出所提供的文本内容 |
WriteValue |
将所提供的值作为单类型值写出 |
WriteWhitespace |
写出给定的空白 |
正如您从表4-7中看到的,为了写入元素、属性和文档,需要调用一个WriteStartXXX函数和一个WriteEndXXX函数。在使用XmlWriter的时候,您并不是简单地写入一个元素;您先写入开始标签,然后写入它的内容,最后写入结束标签。因此,必须跟踪您在文档中所处的位置以保证您在正确的时间调用正确的结束函数。
注意:
除了提供写入XML数据的方法以外,XmlWriter还可以帮助您创建有效的XML文档。例如,XmlWriter不会让您做在标签外面写入属性这样的事情。它还会确保您以正确的顺序写入元素,如将<?xml version=“1.0”?>指令放在<!DOCTYPE>语句之前等等。但是,请注意XmlWriter不会执行任何对DTD或者XML模式的验证。为了执行这些验证,可以使用XmlWriter将文档写入内存流,然后使用XmlNodeReader对象结合XmlWriterSettings对象对内存流进行验证。XmlWriter还会在需要的时候对输出中的特殊字符进行转义操作。例如,它会将&、<和>字符替换为相应的Unicode实体:&、<和>。
1. 开始和结束文档
WriteStartDocument()和WriteEndDocument()函数用于写入XML文档的开始和结束。WriteStartDocument()函数可以写入所有XML文档都会包含的<?xml version=“1.0”?>打开语句,并设置一个布尔值变量用于指示该文档是否是一个单机XML文档(XML文档所需的所有实体声明都包含在文档之内)。如果这个变量为true,则将standalone=“yes”添加至XML声明。
注意:
<?xml>声明在技术上是可选择的,但是W3C XML规范推荐您使用这个声明。您可以在http://www.w3.org/xml上找到这个规范。
WriteEndDocument函数关闭所有打开的属性和元素标签。通常情况下,您会在需要的时候自己关闭元素和属性,但是在您达到文档尾时,调用这个函数是个不错的选择,这样做也仅仅是为了确认。
2. 写入元素
可以通过WriteStartElement()和WriteEndElement()函数配对或者使用WriteElementString()函数来写入元素。WriteElementString()函数是最简单的,因为它允许您在同一时间写入元素的名称和它的内容。缺点是在使用这个函数的时候不能在元素中写入任何属性。
例如,要写入XML元素<city>Seattle</city>,可以简单地使用如下代码:
writer.WriteElementString("city", "Seattle")
但是,这并不总是有用,因为您经常会想写入一个包含属性或者其他元素的元素。为了达到这个目的,您的代码需要调用WriteStartElement(),然后调用XmlWriter的一个或者多个其他方法。例如,下面的代码段写入了一个包含有另外一个元素的元素:
writer.WriteStartElement("name")
writer.WriteElementString("firstName","Nancy")
writer.WriteEndElement()
生成的XML片断如下所示:
<name>
<firstName>Nancy</firstName>
</name>
3. 写入属性
像元素一样,属性也可以使用两种方式写入。一种方式是使用WriteAttributeString()方法,一次性写入属性和属性值。另外一种方式是使用WriteStartAttribute()和WriteEndAttribute()方法来添加属性至元素。例如,如下代码片断使用了第二种方式来添加属性至元素:
writer.WriteStartElement("employee")
writer.WriteStartAttribute("id")
writer.WriteString("1")
writer.WriteEndAttribute()
writer.WriteEndElement()
这段代码生成的XML片断如下所示:
<employee id="1"/>
4. 写入其他数据
XmlWriter类为在输出中写入其他类型的XML内容提供了方法。
● WriteString()方法对于写入字符串内容至XML文件非常有用。它可以用于写入元素和属性的内容,并且它会自动将&、<和>字符替换为相应的Unicode实体。
● WriteCData()方法写入CDATA区域至XML文件。CDATA区域用于包含您不想让XML解析器解析成XML的内容。
● WriteComment()方法插入XML注释至文件中。XML注释就像HTML注释一样:它们都包括在<!--和-->之内。
● WriteRaw()方法可以用于在输出中直接插入XML标记。您应当小心地使用这个函数,因为它不会保证标记是配对的,也不会保证将特殊字符转换为相应的Unicode实体。
在您利用各种Write方法写入XML数据的时候,XmlWriter对象通过在WriteState枚举中设定的值来展现它的状态。表4-8总结了XmlWriter的允许状态。这些值来自于WriteState枚举类型。在各种内部操作发生的时候,XmlWriter应该会正确且迅速地更新它的WriteState属性。
表4-8 WriteState枚举的成员
状 态 |
说 明 |
Attribute |
当写入属性的时候,书写器进入这个状态 |
Closed |
当调用Close方法并且书写器不再用于写入操作的时候,进入这个状态 |
Content |
当写入节点内容的时候,书写器进入这个状态 |
Element |
当写入元素的开始标签的时候,书写器进入这个状态 |
Error |
在写入操作时提示一个错误,并阻止书写器继续操作 |
Prolog |
书写器正在写入格式良好的XML 1.0文档的前言(即用于声明元素名称、属性和数据类型有效标记的构建规则的区域) |
Start |
书写器处于初始状态,并等待书写器的调用 |
既然您已了解了XmlWriter类的基本属性和方法,现在就可以讲解利用这些属性和方法的示例。