图七列出了XML writer的一些状态值(state)。这些值都源于WriteState枚举类。当你创建一个Writer,它的初始状态为Start,表示你将要配置该对象,实际上writer没有开始。下一个状态是Prolog,该状态是当你调用WriteStartDocument方法开始工作的时候设置的。然后,状态的转换就取决于你的写的文档及文档的内容了。Prolog状态一直保留到当你增加一个非元素节点时,例如注释元素,处理指令及文档类型。当第一个节点也就是根节点写完后,状态就变为Element。当你调用WriterStartAtribute方法时状态转换为Attribute,而不是当你调用WriteAtributeString方法写属性时转换为该状态。如果那样的话,状态应该是Element。当你写一个闭标签(>)时,状态会转换成Content。当你写完文档后,调用WriteEndDocument方法,状态就会返回为Start,直到你开始写另一个文档或者把Writer关掉。
|
Writer 把输出文本存在内部的一个缓冲区内。一般情况下,缓冲区会被刷新或者被清除,当Writer被关闭前XML文本应该要写出。在任何时你都可以通过调用Flush方法清空缓冲区,把当前的内容写到流中(通过BaseStream属性暴露流),然后释放部分占用的内存,Writer仍保持为打开状态(open state),可以继续操作。注意,虽然写了部分的文档内容,但是在Writer没有关闭前其它的程序是不能处理该文档的。
可以用两种方法来写属性节点。第一种方法是用WriteStartAtribute方法去创建一个新的属性节点,更新Writer的状态。接着用WriteString方法设置属性值。写完后,用WriteEndElement方法结束该节点。另外,你也可以用WriteAttributeString方法去创建新的属性节点,当writerr的状态为Element时,WriterAttributeString开始工作,它单独创建一个属性。同样的,WriteStartElement方法写节点的开始标签(<),然后你可以随意的设置节点的属性和文本内容。元素节点的闭标签都带”/ >”。如果想写闭标签可以用WriteFullEndElement方法来写。
应该避免传送给写方法的文本中包含敏感的标记字符,例如小于号(<)。用WriteRaw方法写入流的字符串不会被解析,我们可以用它来对xml文档写入特殊的字符串。下面的两行代码,第一行输出的是”<”,第二行输出”<”:
|
读写流
有趣的是,reader(阅读器)和writer类提供了基于Base64 和BinHex编码的读写数据流的方法。WriteBase64 和 WriteBinHex方法的功能与其它的写方法的功能存在着细微的差别。它们都是基于流的,这两个方法的功能像一个byte数组而不是一个string。下面的代码首先把一个string转换成一个byte数组,然后把它们写成一个Base64 编码流。Encoding类的GetBytes静态方法完成转换的任务:
writer.WriteBase64(
Encoding.Unicode.GetBytes(buf),
0, buf.Length*2);
图八中代码演示了把一个string数据转换为Base64 编码的XML流。图九是输出的结果。
Figure 8 Persisting a String Array as Base64
using System;
using System.Text;
using System.IO;
using System.Xml;
class MyBase64Array
{
public static void Main(String[] args)
{
string outputFileName = "test64.xml";
if (args.Length >0)
outputFileName = args[0]; // file name
// 把数组转换成XML
String[] theArray = {"Rome", "New York", "Sydney", "Stockholm",
"Paris"};
CreateOutput(theArray, outputFileName);
return;
}
private static void CreateOutput(string[] theArray, string filename)
{
// 打开XML writer
XmlTextWriter xmlw = new XmlTextWriter(filename, null);
//使子元素根据 Indentation 和 IndentChar 设置缩进。此选项只对元素内容进行缩进
xmlw.Formatting = Formatting.Indented;
//书写版本为“1.0”的 XML 声明
xmlw.WriteStartDocument();
//写出包含指定文本的注释 。
xmlw.WriteComment("Array to Base64 XML");
//开始写出array节点
xmlw.WriteStartElement("array");
//写出具有指定的前缀、本地名称、命名空间 URI 和值的属性
xmlw.WriteAttributeString("xmlns", "x", null, "dinoe:msdn-mag");
// 循环的写入array的子节点
foreach(string s in theArray)
{
//写出指定的开始标记并将其与给定的命名空间和前缀关联起来
xmlw.WriteStartElement("x", "element", null);
//把S转换成byte[]数组, 并把byte[]数组编码为 Base64 并写出结果文本,
要写入的字节数为s总长度的2倍,一个string占的字节数是2字节。
xmlw.WriteBase64(Encoding.Unicode.GetBytes(s), 0, s.Length*2);
//关闭子节点
xmlw.WriteEndElement();
}
//关闭根节点,只有两级
xmlw.WriteEndDocument();
// 关闭writer
xmlw.Close();
// 读出写入的内容
XmlTextReader reader = new XmlTextReader(filname);
while(reader.Read())
{
//获取节点名为element的节点
if (reader.LocalName == "element")
{
byte[] bytes = new byte[1000];
int n = reader.ReadBase64(bytes, 0, 1000);
string buf = Encoding.Unicode.GetString(bytes);
Console.WriteLine(buf.Substring(0,n));
}
}
reader.Close();
}
}