这篇论文说明了修改 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 日志文件中。

None.gif using  System;

None.gif using  System.IO;

None.gif using  System.Xml;  
None.gif

ExpandedBlockStart.gifContractedBlock.gif public   class  Test dot.gif {  
ExpandedSubBlockStart.gifContractedSubBlock.gifpublic static void Main(string[] args)dot.gif{

InBlock.gif

InBlock.gifStreamWriter sw = File.AppendText("logfile-entries.txt");

InBlock.gifXmlTextWriter xtw = new XmlTextWriter(sw);  
InBlock.gif

InBlock.gifxtw.WriteStartElement("event");  
InBlock.gifxtw.WriteElementString("ip", "192.168.0.1");

InBlock.gifxtw.WriteElementString("http_method", "POST");

InBlock.gifxtw.WriteElementString("file", "comments.aspx");

InBlock.gifxtw.WriteElementString("date", "1999-05-05T19:25:13.238220-08:00");  
InBlock.gif

InBlock.gifxtw.Close();

InBlock.gif

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}

java 修改xml指定值 如何修改xml中的数据_XML


java 修改xml指定值 如何修改xml中的数据_XML


一旦条目被追加到文本文件中,使用传统的 XML 处理方法,就可以处理 XML 日志文件中的条目。下面的代码使用 XPath 遍历了 logfile.xml 中的日志事件,同时列出了它们被访问时的文件以及被访问的文件。

using  System;

None.gif using  System.Xml;  
None.gif

ExpandedBlockStart.gifContractedBlock.gif public   class  Test2 dot.gif {

InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifpublic static void Main(string[] args)dot.gif{

InBlock.gif

InBlock.gifXmlValidatingReader vr =  
InBlock.gifnew XmlValidatingReader(new XmlTextReader("logfile.xml"));

InBlock.gifvr.ValidationType = ValidationType.None;  
InBlock.gifvr.EntityHandling = EntityHandling.ExpandEntities;  
InBlock.gif

InBlock.gifXmlDocument doc = new XmlDocument();  
InBlock.gifdoc.Load(vr);  
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifforeach(XmlElement element in doc.SelectNodes("//event"))dot.gif{

InBlock.gif

InBlock.gifstring file = element.ChildNodes[2].InnerText;  
InBlock.gifstring date = element.ChildNodes[3].InnerText;  
InBlock.gif

InBlock.gifConsole.WriteLine("{0} accessed at {1}", file, date);

InBlock.gif

ExpandedSubBlockEnd.gif}  
ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}  

None.gif

None.gif

上面的代码导致了下面的输出:

index.html accessed at 2004-04-01T17:35:20.0656808-08:00
stylesheet.css accessed at 2004-04-01T17:35:23.0656120-08:00
logo.gif accessed at 2004-04-01T17:35:25.238220-08:00
comments.aspx accessed at 1999-05-05T19:25:13.238220-08:00

更改 XmlReader 为 XmlWriter
在某些情况下,除了只将元素追加到根元素中外,还需要对 XML 文件执行更复杂的操作。例如,要筛选日志文件中的每一个条目,而这些条目在存档到日志文件前不符合某些特殊标准。要完成此任务的一种方法是将 XML 文件加载到 XmlDocument 中,然后通过 XPath 选择感兴趣的事件。但是,这样做涉及将整个文档加载到内存中,如果文档太大,则这种做法会受到限制。另一种选择方法为了这种任务会涉及使用 XSLT,但是由于整个 XML 文档需要保存到内存中,这种方法会和 XmlDocument 方法一样遇到相同的问题。另外,由于开发人员不熟悉 XSLT,了解如何正确使用模板匹配时会遇到较大的困难。

要解决如何处理大型 XML 文档问题的一种方法是使用 XmlReader 读取 XML,读取的同时使用 XmlWriter 将其写出。使用这种方法,整个文档不会同时存入内存中,对 XML 可以进行更精确的更改而不只是追加元素。下面的代码示例读取前面部分的 XML 文档,筛选出所有 ip 元素的值为 "127.0.0.1" 的事件后将其保存为存档文件。

using  System;

None.gif using  System.Xml;  
None.gif using  System.IO;

None.gif using  System.Text;

ExpandedBlockStart.gifContractedBlock.gif public   class  Test2 dot.gif {

InBlock.gifstatic string ipKey;

InBlock.gifstatic string httpMethodKey;

InBlock.gifstatic string fileKey;  
InBlock.gifstatic string dateKey;

InBlock.gifstatic string referrerKey;  
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifpublic static void WriteAttributes(XmlReader reader, XmlWriter writer)dot.gif{

InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifif(reader.MoveToFirstAttribute())dot.gif{

ExpandedSubBlockStart.gifContractedSubBlock.gifdodot.gif{

InBlock.gifwriter.WriteAttributeString(reader.Prefix,  
InBlock.gifreader.LocalName,  
InBlock.gif

InBlock.gifreader.NamespaceURI,

InBlock.gifreader.Value);  
ExpandedSubBlockEnd.gif}while(reader.MoveToNextAttribute());

InBlock.gifreader.MoveToElement();  
ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}

InBlock.gif

InBlock.gifpublic static void WriteEvent(XmlWriter writer, string ip,

InBlock.gifstring httpMethod, string file,

ExpandedSubBlockStart.gifContractedSubBlock.gifstring date, string referrer)dot.gif{

InBlock.gif

InBlock.gifwriter.WriteStartElement("event");  
InBlock.gifwriter.WriteElementString("ip", ip);

InBlock.gifwriter.WriteElementString("http_method", httpMethod);

InBlock.gifwriter.WriteElementString("file", file);

InBlock.gifwriter.WriteElementString("date", date);  
InBlock.gifif(referrer != null) writer.WriteElementString("referrer", referrer);

InBlock.gifwriter.WriteEndElement();  
InBlock.gif

ExpandedSubBlockEnd.gif}  
InBlock.gif

InBlock.gifpublic static void ReadEvent(XmlReader reader, out string ip,

InBlock.gifout string httpMethod, out string file,

ExpandedSubBlockStart.gifContractedSubBlock.gifout string date, out string referrer)dot.gif{

InBlock.gif

InBlock.gifip = httpMethod = file = date = referrer = null;  
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifwhile( reader.Read() && reader.NodeType != XmlNodeType.EndElement)dot.gif{  
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifif (reader.NodeType == XmlNodeType.Element) dot.gif{

InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifif(reader.Name == ipKey)dot.gif{  
InBlock.gifip = reader.ReadString();  
ExpandedSubBlockStart.gifContractedSubBlock.gif}else if(reader.Name == httpMethodKey)dot.gif{  
InBlock.gifhttpMethod = reader.ReadString();

ExpandedSubBlockStart.gifContractedSubBlock.gif}else if(reader.Name == fileKey)dot.gif{  
InBlock.giffile = reader.ReadString();

ExpandedSubBlockStart.gifContractedSubBlock.gif}else if(reader.Name == dateKey)dot.gif{  
InBlock.gifdate = reader.ReadString();

InBlock.gif// reader.Read(); // 使用结尾标记

ExpandedSubBlockStart.gifContractedSubBlock.gif}else if(reader.Name == referrerKey)dot.gif{  
InBlock.gifreferrer = reader.ReadString();

ExpandedSubBlockEnd.gif}

ExpandedSubBlockEnd.gif}//if  
ExpandedSubBlockEnd.gif}//while  
ExpandedSubBlockEnd.gif}

InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gifpublic static void Main(string[] args)dot.gif{

InBlock.gifstring ip, httpMethod, file, date, referrer;  
InBlock.gif//使用用于进行比较的字符串设置 XmlNameTable

InBlock.gifXmlNameTable xnt = new NameTable();  
InBlock.gifipKey = xnt.Add("ip");  
InBlock.gifhttpMethodKey = xnt.Add("http_method");  
InBlock.giffileKey = xnt.Add("file");

InBlock.gifdateKey = xnt.Add("date");

InBlock.gifreferrerKey = xnt.Add("referrer");

InBlock.gif

InBlock.gif//使用上面的 XmlNameTable 加载 XmlTextReader  
InBlock.gifXmlTextReader xr = new XmlTextReader("logfile.xml", xnt);

InBlock.gifxr.WhitespaceHandling = WhitespaceHandling.Significant;

InBlock.gif

InBlock.gifXmlValidatingReader vr = new XmlValidatingReader(xr);

InBlock.gifvr.ValidationType = ValidationType.None;

InBlock.gifvr.EntityHandling = EntityHandling.ExpandEntities;  
InBlock.gif

InBlock.gif

InBlock.gifStreamWriter sw =  
InBlock.gifnew StreamWriter ("logfile-archive.xml", false, Encoding.UTF8 );  
InBlock.gifXmlWriter xw = new XmlTextWriter (sw);  
InBlock.gif

InBlock.gifvr.MoveToContent(); // 移到文档元素  
InBlock.gifxw.WriteStartElement(vr.Prefix, vr.LocalName, vr.NamespaceURI);

InBlock.gifWriteAttributes(vr, xw);  
InBlock.gif

InBlock.gifvr.Read(); // 移到文档元素的第一个 <event> 子元素

InBlock.gif// 写出不是 127.0.0.1(本地主机)中的事件

InBlock.gifdo

ExpandedSubBlockStart.gifContractedSubBlock.gifdot.gif{

InBlock.gifReadEvent(vr, out ip, out httpMethod,  
InBlock.gifout file, out date, out referrer);

ExpandedSubBlockStart.gifContractedSubBlock.gifif(!ip.Equals("127.0.0.1"))dot.gif{

InBlock.gifWriteEvent(xw,ip, httpMethod, file, date, referrer);  
ExpandedSubBlockEnd.gif}

InBlock.gifvr.Read(); //移到下一个 <event> 元素或 <logfile> 的结尾标记

ExpandedSubBlockEnd.gif} while(vr.NodeType == XmlNodeType.Element);

InBlock.gif

InBlock.gifConsole.WriteLine("Done");

InBlock.gif

InBlock.gifvr.Close();

InBlock.gifxw.Close();

ExpandedSubBlockEnd.gif}

ExpandedBlockEnd.gif}


上面的代码示例在写入到 logfile-archive.xml 文件中时会导致下面的输出:

<logfile>
<event>
<ip>192.168.0.1</ip>
<http_method>POST</http_method>
<file>comments.aspx</file>
<date>1999-05-05T19:25:13.238220-08:00</date>
</event>
</logfile>

除了使用 XmlReader 到 XmlWriter 的链之外,上面代码的另一个有趣方面是,使用 ReadEvent() 方法检查元素标记名称时使用 NameTable 提高了文本比较的性能。在 XmlReader 中使用这种方法检查元素的标记名称的优点在如下的 MSDN 文档主题中进行了概述:Object Comparison Using XmlNameTable with XmlReader(英文)。