Top
首页 > 老文章 > 正文

在Managed C++中处理XML

使用.NET中具备的XML功能为我们的程序设计带来很多优越性,在这篇文章中,我将用.NET架构来处理XML...
发布时间:2002-09-09 09:53        来源:        作者:Kate Gregory著 申小玲编译
在这篇文章中,我将用.NET框架来处理XML。 使用.NET中具备XML功能所带来的优越性包括: ● 无需任何安装、配置或重新分配,反正你的apps也是需要这个框架的,而只要你有这个框架,就万事俱备了; ● 编码更简单,因为你不是在处理COM。比如,你不必要调用CoInitialize() 和 CoUninitialize(); ● 具有比MSXML4更多的功能。
XML实例
我将用下面的例子来加以说明:
<?xml version="1.0" encoding="utf-8" ?> 
<PurchaseOrder>
<Customer id="123"/>
<Item SKU="1234" Price="4.56" Quantity="1"/>
<Item SKU="1235" Price="4.58" Quantity="2"/>
</PurchaseOrder>
用XmlDocument加载XML 处理XML的classes放在System::Xml namespace 中。XmlDocument表示一个DOM 文件,即XML被装载的子目录。这和在MSXML4方法中的DOMDocument是一样的。下面是一个简单的Managed C++应用程序,在内存中装入了XML文件:
#include "stdafx.h"
#using <mscorlib.dll>
#include <tchar.h>
using namespace System;
#using <System.Xml.dll>
using namespace System::Xml;
// This is the entry point for this application
int _tmain(void)
{
  XmlDocument* xmlDoc = new XmlDocument();
  try
  {
    xmlDoc->Load("sample.xml");
    System::Console::WriteLine("Document loaded ok." );
  }
  catch (Exception *e)
  {
    System::Console::WriteLine("load problem");
    System::Console::WriteLine(e->Message);
  }
  return 0;
}
#using 语句非常重要。没有它,就会出现一些奇怪的编译错误,如'Xml' : is not a member of 'System' 或 'Xml' : a namespace with this name does not exist. 在C#或VB.NET中,有一个Project,Add References 菜单项目自动为你完成这项工作,但是在C++中,编程者必须自己去完成。你可以在在线帮助中找到class或namespace汇编。 另外注意到,在编码中没有象COM方法中那样使用Load()返回值。如果不能加载XML,加载程序将报告异常。 文档内容的简单算法 这里是.NET方式中相应的编码。
xmlDoc->Load("sample.xml");
double total = 0;
System::Console::WriteLine("Document loaded ok." );
XmlNodeList* items = xmlDoc->GetElementsByTagName("Item");
long numitems = items->Count;
for (int i=0;i<numitems;i++)
{
  XmlNode* item = items->Item(i);
  double price =
    Double::Parse(item->Attributes->GetNamedItem("Price")->
                  get_Value());
  double qty =
    Double::Parse(item->Attributes->GetNamedItem("Quantity")->
                  get_Value());
  total += price * qty;
}
System::Console::WriteLine("Purchase Order total is ${0}",
                           __box(total));
我只是在测试block中加了这段编码。如果你需要将一个应用程序从COM和MSXML4转换为.NET,要注意到capitalization有很大不同,其功能仅仅是返回你所需要的值,而不是产生一个指针指向它们为你指定的目标。和我在这儿所做的一样,那样会使连接成串的指令变得更简单。由于Managed C++ 对类型比较挑剔,只好使用Double::Parse() 将串变成编号,并且在传递给WriteLine()之前汇总。 本程序运行时,会显示:
Document loaded ok.
Purchase Order total is $13.72
如果你想退出XML,只需要一行编码:
System::Console::WriteLine(xmlDoc->InnerXml);
InnerXml 是String*,因此将其传递给WriteLine() 是没有问题的,不必要借助于任何中间变量。
XML 在 .NET 中处于什么位置?
在整个.NET体系中你将看到适用XML的多处地方。例如,你只要在申明中增加“可序列化”这一属性,任何一个类都可以把自己转换为 XML 或者从XML 转换回来。 下面以一个简单的类为例子,你可以把它转成为XML格式泵出,或者从XML格式输入赋值。
[Serializable]
public __gc class PurchaseOrder
{
public:
int customer;
// other elements to be added
PurchaseOrder(int id) {customer=id;}
PurchaseOrder() {customer=0;}
};
你为这个类加上可序列化(Serializable)标记。只有公开的变量才能这样序列化,而且这个类必须有一个隐含的构造函数。一旦满足了这些限制条件并且进行编译之后,事情就容易了。下面是怎样把这个对象卸出到文件中:
PurchaseOrder* po =
new PurchaseOrder(Int32::Parse(xmlDoc->
GetElementsByTagName("Customer")->Item(0)->
Attributes->GetNamedItem("id")->get_Value()));
System::Xml::Serialization::XmlSerializer* ser =
new System::Xml::Serialization::XmlSerializer(po->GetType());
System::IO::TextWriter* writer =
new System::IO::StreamWriter("po.xml");
ser->Serialize(writer,po);
writer->Close();
如果采用名字空间可以大大提高这段代码的可读性,但是这个例子是想展示和我所用的类所关联的完整的名字空间。第一行特别长,从头贯穿XML文件查找客户 (customer)标记,找到第一个后,查看它的标识(id) 属性,用它的值来构造采购单(PurchaseOrder)。然后,我创建了一个序列转换器和一个书写器,并且调用序列转换器的 serialize() 方法。输出的 po.xml 如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<PurchaseOrder xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<customer>123</customer>
</PurchaseOrder>
如果采购单是一个很大很复杂的类,可能是用.NET的某个收集类来保存一组事项,那我还是只需要这一小段代码把它按 XML格式输出:创建一个序列转换器和一个书写器,然后调用序列转换器的 serialize() 方法。从 XML 格式恢复对象时,顺序刚好相反:
PurchaseOrder* po2 = new PurchaseOrder();
ser = new System::Xml::Serialization::XmlSerializer(po2->GetType());
System::IO::FileStream* fs =
new System::IO::FileStream("po.xml",
System::IO::FileMode::Open);
po2 = (PurchaseOrder*) ser->Deserialize(fs);
System::Console::WriteLine("Rehydrated customer is {0}.",
__box(po2->customer));
如果你在ASP.NET或者Windows应用程序中使用数据网格(DataGrids),你可以从一个XML文件加载它们(很适合用来作快速演示),或者在你需要的时候,作为一种调试手段让它们把自己卸载到XML。只需简单地创建一个空的数据集(DataSet)对象,调用它的 Realxml() 方法来用一个文件中的 XML 填充它,然后把它作为你的数据网格的数据源去调用 DataBind() 方法。也可以用如下的方法从数据网格中取得 XML:
xmlstring = DataGrid1->DataSource->GetXml();
使用 .NET 类库你还可以用XML干很多的事。用一两行就可以产生 XML,从一种排放形式转换成另一种,或者是找到文档的某个子集。 利用Visual Studio中对于模式(schema)的支持,你可以生成一个匹配某个XML范例文件的模式,或者在编辑 XML时使用 Intellisense, 它知道你正在使用的模式, 当你打字输入时,随时提醒你当前允许使用的元素或者属性。XML处在.NET革命的心脏,所以你应该尽早了解它。 关于作者 Kate Gregory 是 Gregory Consulting Limited (http://www.gregcons.com/) 的创始人之一。 2002年一月,她被任命为MSDN在加拿大多伦多区的总监。她的 C++ 经验追溯到 Visual C++ 出现之前。在.NET, Visual Studio, XML, UML, C++, Java 和互联网等方面,她是各大学和微软活动中知名的演讲人和讲师。Kate 和她在Gregory Consulting的同事们擅长把软件开发和网站开发结合起来,创建生动的网站。她们生产高质量的通用的和定制的软件零件,用于网页和其他应用程序。 Kate 为 Que 写过很多书籍,包括“使用Visual C++ .NET 特辑”。 (责任编辑 Sunny
加载更多

专题访谈

合作站点
stat