- 你所在位置:首页 〉VS.net〉XML〉XML经验〉XML 开发人员的 SAX2 快速入门
- XML 开发人员的 SAX2 快速入门
- 作者:佚名 文章来源:http://msdn2.microsoft.com/zh-cn/default.aspx 发布日期:2007-07-07 浏览次数:678
-
- 打印这篇文章
-
什么是 SAX2?
SAX2,即 Simple API for XML,是基于事件的 XML 分析的标准接口的最新版本。SAX2 提供了使用“文档对象模型 (DOM)”处理 XML 文档的快速、低内存的另一种方法。在使用 DOM 分析 XML 文件时,它在内存中建立了完整的文档树。相比而言,SAX2 将遍历文档,并将新元素的开始或结束等通知分析事件的调用应用程序。使用 SAX2 的一个最佳功能是分析长文档。例如,用 SAX2 分析器,应用程序可以监视发生的事件,只将文档中必要的部分读入内存。
Microsoft 在 MSXML3.DLL 中为 SAX2 接口提供了完全兼容的 COM 实现 (MSXML SAX2) 。作为对 MSXML SAX2 的快速简介,并且为了帮助您开始用它的接口来建立应用程序,本文介绍如何快速建立“骨架”应用程序,它使用 MSXML SAX2 读取 XML 文档,并在控制台上打印文档的标记。在理解了用 MSXML SAX2 建立应用程序的基本原理之后,无疑您会清楚如何利用基于事件的分析建立应用程序。
如何使用 MSXML SAX2?
SAX2 是一种“推进模型”分析器。换句话说,您提供了许多处理程序,而在发生特定事件时(例如开始一个文档,或一个元素的开始和结束),分析器便调用您提供的处理程序。SAX2 分析器生成一些种类的事件,包括在 XML 文档内容中发生的事件、在 DTD 中发生的事件和错误事件。要处理这些事件,必须实现相应的处理程序类,它包含处理相应事件的方法。请注意,您只需要为这些要处理的事件实现处理程序。如果没有为特定类型的事件实现处理程序,那么该事件将被忽略。
例如,本文中介绍的“命令行”应用程序只有一个处理程序 — 内容处理程序,它是通过实现扩展 ISAXContentHandler 接口的类创建的。请注意,在 Visual C++ 中不需要创建功能完整的 COM 对象。对于您创建的每个处理程序类来说,需要实现响应 XML 分析事件的方法。
在为要处理的事件创建了必要的处理程序类之后:
- 创建 SAXXMLReader 实例。
- 设置处理程序类。
- 设置 XML 文档的来源。
- 开始分析。
在分析器读取 XML 文档时,它将调用包含在实现的处理程序中的方法。
“快速入门”应用程序代码
正如以前所提到的,本文将介绍如何建立非常简单的命令行应用程序,它能够读取 XML 文件,并将文件的标记打印到控制台窗口。应用程序只实现了内容处理程序。应用程序包括下列文件:
- MyContent.h 内容处理程序的头文件。
- MyContent.cpp 内容处理程序的实现。
- TestSax.cpp “命令行”控制台应用程序。
内容处理程序头文件
为了实现内容处理程序,必须首先为它创建头文件。我们为该应用程序调用文件 MyContent.h。
#include xmlsax.h" // 包括头文件。 class MyContent : public ISAXContentHandler { public: MyContent(); // 定义建立函数和解除函数。 virtual ~MyContent(); // 从 ISAXContentHandler 复制所有的方法。 // 接口... virtual HRESULT STDMETHODCALLTYPE StartDocument(void); virtual HRESULT STDMETHODCALLTYPE EndDocument(void); virtual HRESULT STDMETHODCALLTYPE StartPrefixMapping(const wchar_t__RPC_FAR *pwchPrefix,int cchPrefix,const wchar_t __RPC_FAR *pwchUri,int cchUri); // ...和底层的 IUnknown 接口... long __stdcall QueryInterface(const struct _GUID &,void ** ); unsigned long __stdcall AddRef(void); unsigned long __stdcall Release(void); // ...和添加任何内容来简化实现。 private: void prt ( char * pszFmt, const wchar_t __RPC_FAR *pwchVal, int cchVal); };内容处理程序实现
下一步是实现 MyContent 类。该文件也相对简单。
#include "stdafx.h" // 我们需要头文件... #include
#include #include "MyContent.h" // 通常在建立函数和解除函数中不需任何操作, // 但如果有的话,则在此完成。 MyContent::MyContent() {} MyContent::~MyContent() {} // 现在完成 IUnknown 填充。 // (然而,请牢记,若希望将处理程序作为 COM 对象来实现, // 可以添加比用这些方法显示的 // 更多的功能) long __stdcall MyContent::QueryInterface(const struct _GUID &,void ** ) { return 0; } unsigned long __stdcall MyContent::AddRef() { return 0; } unsigned long __stdcall MyContent::Release() { return 0; } //现在开始着手业务。 // 首先确定您需要的和不需要的事件。 // 对于不需要的方法,处理很简单: HRESULT STDMETHODCALLTYPE MyContent::StartDocument() { return S_OK; // 返回 S_OK 以继续。 // 任何返回的错误代码都将中止语法分析。 } // 对于需要的事件,您可随意处理! HRESULT STDMETHODCALLTYPE MyContent::StartElement( /* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri, /* [in] */ int cchNamespaceUri, /* [in] */ const wchar_t __RPC_FAR *pwchLocalName, /* [in] */ int cchLocalName, /* [in] */ const wchar_t __RPC_FAR *pwchRawName, /* [in] */ int cchRawName, /* [in] */ ISAXAttributes __RPC_FAR *pAttributes) { //我想打印标志名称。 prt("\n<%s>",pwchLocalName,cchLocalName); return S_OK; } //“prt” 是一个专用方法。 // SAX 不使用它。您不必实现它和任何其他 // 专用方法。 // 这仅是快速打印。 void MyContent::prt ( char * pszFmt, const wchar_t __RPC_FAR *pwchVal, int cchVal ) { static wchar_t fmt[1000], val[1000]; mbstowcs( fmt, pszFmt, 999 ); fmt[999] = 0; wcsncpy( val, pwchVal, (cchVal>999?999:cchVal+1) ); val[999] = 0; wprintf(fmt,val); } 主程序
最后,创建了启动整个过程的“主程序”。它提供了命令行接口,通过实例化实现 SAXXMLReader 接口的类来创建分析器,通过实例化 MyContent 类来创建内容处理程序,并且在分析器中注册了内容处理程序。
#include "stdafx.h" // 您再次需要头文件。 #include "stdio.h" // 这只是在打印时需要。 #include "xmlsax.h" #include "xmlsax_i.c" // 这不是真正的头文件。 // 建议单独对其编译。在此 // 只是提醒您必须编译才能获得 // 常数。 #include "MyContent.h" int main(int argc, char* argv[]) // 开始! { CoInitialize(NULL); // 启动 COM 有点不可思议。您可能 // 想使用 CoInitializeEx。 ISAXXMLReader* pRdr = NULL; // 创建分析程序。(会更不可思议...) HRESULT hr = CoCreateInstance(CLSID_SAXXMLReader, NULL, CLSCTX_ALL, IID_ISAXXMLReader, (void **)&pRdr); if(!FAILED(hr)) { MyContent * pMc = new MyContent(); // 设置您自己的内容 // 处理程序(以及 // 其他程序)。 hr = pRdr->PutContentHandler(pMc); // 在现实中,请检查 // 此 hr! static wchar_t URL[1000]; // ParseURL 应是 Unicode 字符串, // argv[1] 是 ASCII。 mbstowcs( URL, argv[1], 999 ); // 验证您是否有 argv[1]。 hr = pRdr->ParseURL(URL,-1); // 以及语法分析! pRdr->Release(); // 现在只有一些清除工作... } else { printf("\nUh-oh... %08X\n\n", hr); // 希望这不会发生, // 但是要作好准备。 } CoUninitialize(); // 最后,再一次, // 未初始化 COM 有点不可思议。 return 0; }下一步
本文的目的是简单介绍 SAX2,介绍可以作为您自己应用程序起点的应用程序。有关 MSXML SAX2 接口的详细信息,请参阅“2000 年 5 月技术预览”所附的“Microsoft XML SDK 3.0”中的“SAX2 开发人员指南”和“SAX2 参考”。有关处理程序实现的其他代码示例,请下载本文提供的示例代码。
- 创建 SAXXMLReader 实例。
- 打印这篇文章
- 与本文主题相关的文章
-
- 返回首页
