方法可以接受 XML 输入或者返回 XML 作为输出
当设计生成或使用 XML 的方法时,开发人员有责任使这样的方法在接受输入时具有灵活性。当方法接受 XML 作为输入时,您可以将这些方法分为要求在适当位置修改数据的方法,以及只需对 XML 进行只读访问的方法。唯一一个支持读写访问的“XML 常见疑点”是 XmlDocument。下面的代码示例显示了这样一个方法:
public void ApplyDiscount(XmlDocument priceList){
foreach(XmlElement price in priceList.SelectNodes("//price")){
price.InnerText = (Double.Parse(price.InnerText) * 0.85).ToString();
}
}
对于需要对 XML 进行只读访问的方法,有两个主要选项:
• XmlReader
• XPathNavigator
<items>
<compact-disc>
<price>16.95</price>
<artist>Nelly</artist>
<title>Nellyville</title>
</compact-disc>
<compact-disc>
<price>17.55</price>
<artist>Baby D</artist>
<title>Lil Chopper Toy</title>
</compact-disc>
</items>
XmlReader:
public static void PrintArtistAndPrice(XmlReader reader){
reader.MoveToContent(); //move from root node to document element (items)
/* 保持读取,直至获得第一个 <artist> 元素 */
while(reader.Read()){
if((reader.NodeType == XmlNodeType.Element) && reader.Name.Equals("artist")){
artist = reader.ReadElementString();
title = reader.ReadElementString();
break;
}
}
Console.WriteLine("Artist={0}, Title={1}", artist, title);
}
}
XPathNavigator:
public static void PrintArtistAndPrice(XPathNavigator nav){
XPathNodeIterator iterator = nav.Select("/items/compact-disc[1]/artist
| /items/compact-disc[1]/title");
iterator.MoveNext();
Console.WriteLine("Artist={0}", iterator.Current);
iterator.MoveNext();
Console.WriteLine("Title={0}", iterator.Current);
}
准则 接受或返回 XML 的方法应有助于返回 XmlReader 或 XPathNavigator,除非用户希望能够编辑 XML 数据(此时应使用 XmlDocument)。
上述准则的意思是指返回 XML 的方法应有助于返回 XmlReader,因为它比其他任何类型都适用于更多用户的情况。此外,当方法的调用方需要更多功能时,它们可以从返回的 XmlReader 加载 XmlDocument 或 XPathDocument。
将对象转换为 XML
XML 作为信息交换的通用语言已无所不在,这使其成为要以 XML 表示自身的某些对象的显而易见的选择,这些对象或者是出于序列化目的,或者是为了获得对其他 XML 技术的访问(如使用 XPath 进行查询或使用 XSLT 进行转换)。
当出于序列化目的将对象转换成 XML 时,显然应选择使用 XML Serialization technology in the .NET Framework(英文)。但是,在某些情况下,您对生成的 XML 所需的控制可能比 XmlSerializer 所能提供的更多。在这种情况下,工具包中的 XmlWriter 便是一个很有用的类,因为它使您不再需要该类的结构与所生成的 XML 之间存在一对一映射。下例显示了通过使用 XmlWriter 序列化 Email 类(前面几部分中已经提到)而生成的 XML。
public void Save(XmlWriter writer){
writer.WriteStartDocument();
writer.WriteStartElement("email");
writer.WriteStartElement("headers");
writer.WriteStartElement("header");
writer.WriteElementString("name", "to");
writer.WriteElementString("value", this.To);
writer.WriteEndElement(); //标题
writer.WriteStartElement("header");
writer.WriteElementString("name", "from");
writer.WriteElementString("value", this.From);
writer.WriteEndElement(); //标题
writer.WriteStartElement("header");
writer.WriteElementString("name", "subject");
writer.WriteElementString("value", this.Subject);
writer.WriteEndElement(); //标题
writer.WriteStartElement("header");
writer.WriteElementString("name", "sent");
writer.WriteElementString("value", XmlConvert.ToString(this.Sent));
writer.WriteEndElement(); //标题
writer.WriteEndElement(); //标题;
writer.WriteStartElement("body");
writer.WriteRaw(this.Body);
writer.WriteEndDocument(); //关闭所有打开的标记
}
这段代码生成下面的 XML 文档
<email>
<headers>
<header>
<name>收件人</name>
<value>michealb@example.org</value>
</header>
<header>
<name>发件人</name>
<value>dareo@example.com</value>
</header>
<header>
<name>主题</name>
<value>Hello World</value>
</header>
<header>
<name>发送时间</name>
<value>2004-03-05T15:54:13.5446771-08:00</value>
</header>
</headers>
<body><p>Hello World 是我最喜欢的示例应用程序。</p></body>
</email>
如果要求提供一种方式,使类可以更完全地参与到 XML 世界中(如与XPath 或 XSLT 等 XML 技术进行交互),则该类的最佳选择是实现 IXPathNavigable 接口,并为该类提供 XPathNavigator。这样做的一个示例是 ObjectXPathNavigator,它为那些使您可以在上述对象上执行 XPath 查询或运行 XSLT 转换的任意对象提供了 XML 视图。
准则 如果对象出于序列化目的要以 XML 来表示其自身,当其需要获得的 XML 序列化过程控制比 XmlSerializer 所提供的更多时,则应使用 XmlWriter。如果对象要以 XML 来表示其自身,以便能够完全以 XML 世界成员的身份参与到其中(如允许在此对象上进行 XPath 查询或 XSLT 转换),则此对象应实现 IXPathNavigable 接口。
结论
在将来的 .NET Framework 版本中,将会更加强调基于光标的 XML API(如由 IXPathNavigable 接口公开的 XPathNavigator)。这类光标将成为与 .NET Framework 中的 XML 进行交互的主要机制。
Dare Obasanjo 是 Microsoft WebData 小组的成员,除其他事务外,该小组还开发了 .NET Framework 的 System.Xml 和 System.Data 命名空间、Microsoft XML 核心服务 (MSXML) 以及 Microsoft 数据访问组件 (MDAC) 中的组件。
[1] [2]
