引言
随着 XML 成为大型信息源的常用表示格式,开发人员编辑大型 XML 文件时开始遇到问题。对于处理大型日志文件以及经常需要为这些文件追加信息的应用程序,尤其如此。编辑 XML 文件最直接的方法是,将其加载到 XmlDocument 中,在内存中修改文档,然后将其保存回磁盘。但是,这样做意味着要将整个 XML 文档加载到内存中,由于文档太大或应用程序需要的内存不够,这种方法可能会行不通。
这篇论文说明了修改 XML 文档的一些可供选择的方法,这些方法不涉及将文档加载到 XmlDocument 实例中的内容。
使用 XML 包含方法
建议的第一种方法对于向 XML 日志文件追加值最为有用。开发人员面临的常见问题是需要一种能够将新条目简单地追加到日志文件中而不用加载文档的方法。因为 XML 具有良好结构规则,所以使用传统方式(这种方法会因为日志文件格式不正确而结束日志文件)来向 XML 日志文件追加条目通常是非常困难的。
要说明的第一种方法是针对这样的情形,即目的是能够将条目快速地追加到 XML 文档中。这种方法包括创建两个文件。第一个文件是格式正确的 XML 文件,第二个是 XML 片段。格式正确的 XML 文件包括 XML 片段,XML 片段使用 DTD 中声明的 external entity 或者使用 xi:include element 。使用包含文件,通过在进行处理过程中简单地追加到 XML 文件,可以有效地更新文件包含 XML 片段的方法。包含文件和被包含文件的示例如下所示:
Logfile.xml:
<?xml version="1.0"?>
<!DOCTYPE logfile [
<!ENTITY events
SYSTEM "logfile-entries.txt">
]>
<logfile>
&events;
</logfile>
Logfile-events.txt:
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>index.html</file>
<date>2004-04-01T17:35:20.0656808-08:00</date>
</event>
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>stylesheet.css</file>
<date>2004-04-01T17:35:23.0656120-08:00</date>
<referrer>http://www.example.com/index.html</referrer>
</event>
<event>
<ip>127.0.0.1</ip>
<http_method>GET</http_method>
<file>logo.gif</file>
<date>2004-04-01T17:35:25.238220-08:00</date>
<referrer>http://www.example.com/index.html</referrer>
</event>
logfile-entries.txt 文件包括一个 XML 片段,并且可以使用典型的文件 IO 方法有效地进行更新。下面的代码说明了如何通过将条目追加到文本文件的结尾来将它添加到 XML 日志文件中。
using System;
using System.IO;
using System.Xml;
public class Test{
public static void Main(string[] args){
StreamWriter sw = File.AppendText("logfile-entries.txt");
XmlTextWriter xtw = new XmlTextWriter(sw);
xtw.WriteStartElement("event");
xtw.WriteElementString("ip", "192.168.0.1");
xtw.WriteElementString("http_method", "POST");
xtw.WriteElementString("file", "comments.aspx");
xtw.WriteElementString("date", "1999-05-05T19:25:13.238220-08:00");
xtw.Close();
}
}
一旦条目被追加到文本文件中,使用传统的 XML 处理方法,就可以处理 XML 日志文件中的条目。下面的代码使用 XPath 遍历了 logfile.xml 中的日志事件,同时列出了它们被访问时的文件以及被访问的文件。
using System;
using System.Xml;
public class Test2{
public static void Main(string[] args){
XmlValidatingReader vr =
new XmlValidatingReader(new XmlTextReader("logfile.xml"));
vr.ValidationType = ValidationType.None;
vr.EntityHandling = EntityHandling.ExpandEntities;
XmlDocument doc = new XmlDocument();
doc.Load(vr);
foreach(XmlElement element in doc.SelectNodes("//event")){
string file = element.ChildNodes[2].InnerText;
string date = element.ChildNodes[3].InnerText;