Compact Framework中调用tinyXml解析XML

   在CF中,提供解析XML的类有很多,但是普遍面临的一个问题就是,解析速度实在是太慢了,严重影响了用户体验.C++程序员一般用tinyXml来解析XML文件,在CF中,我们也可以通过平台调用来使用tinyXml.

首先,我们看看需要解析的xml文件结构,我们需要程序返回channel下的所有item节点:

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/"  xmlns:atom="http://www.w3.org/2005/Atom">
   3:   <channel>
   4:     <item>
   5:       <title><![CDATA[Google]]></title>
   6:       <description><![CDATA[by Susan Boyle<br/><img src="http://www.google.cn/intl/zh-CN/images/logo_cn.gif" alt="image" />]]></description>
   7:       <link>http://g.cn</link>
   8:       <guid isPermaLink="false">ZD-FT13416</guid>
   9:       <pubDate>Mon, 04 Jan 2010 13:49:57 +0800</pubDate>
  10:       </item>
  11:   </channel>
  12: <rss>

在c++中,定义一个结构体,用于存放各子节点的数据:

   1: struct ItemInfo
   2: {
   3:     WCHAR title[50];
   4:     WCHAR description[300];
   5:     WCHAR link[200];
   6:     WCHAR guid[50];
   7:     WCHAR pubDate[50];
   8: };

注:

  • 因为在.net中的字符都是宽字符,因此在本文中将所有存储字符的数组定义成WCHAR.
  • c#中的结构体定义可以通过P/Invoke Interop Assistant自动生成.

由于C++生成的dll需要C#来调用,故此,需要声明一个入口:

   1: // xmlPath是设备上的xml文件路径
   2: // itemCount是为了获取总共解析xml文件节点的个数
   3: extern "C" _declspec(dllexport) 
   4: ItemInfo* _stdcall ParserXml(const wchar_t* xmlPath, int *itemCount);

 

将ParsetXml中的代码实现后,编译生成dll….后,开始调用~~~

声明调用函数:

   1: // 实际上,这个也是用P/Invoke Interop Assistant生成的:)
   2: [DllImport(@"\Program Files\Panel\IDEASWM\SmartXml.dll", CharSet = CharSet.Unicode, SetLastError = true)]
   3: public static extern IntPtr ParserXml([System.Runtime.InteropServices.InAttribute()] 
   4:     [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)] string xmlPath, ref int nItemCount);

调用的代码:

   1: IntPtr intPtr = Marshal.AllocHGlobal(0x00000514);
   2: List<XmlInfo> lstXmlInfo = new List<XmlInfo>();
   3: //这是个结构体,它对应C++中的结构体
   4: XmlInfo xmlInfo; 
   5: int count = 0;
   6:  
   7: // 获取dll返回的结构体数组指针
   8: intPtr = ParserXml(this.localXmlFilePath, ref count);
   9: if (intPtr == IntPtr.Zero)
  10: {
  11:     return;
  12: }
  13:  
  14: for (int i = 0; i < count; i++)
  15: {
  16:     try
  17:     {
  18:         xmlInfo = (XmlInfo)Marshal.PtrToStructure((IntPtr)((UInt32)intPtr + size * i), typeof(XmlInfo));
  19:         this.lstXmlInfo.Add(xmlInfo);
  20:     }
  21:     catch
  22:     {
  23:         continue;
  24:     }
  25: }

注:在项目中调试c++的dll,需要保证C++项目和C#项目处于同一解决方案,然后在C++的[项目属性]里面将[调试]将[远程可执行文件]设置成项目生成的.exe文件,然后将C++项目设为启动项即可.

posted @ 2010-01-25 11:35  Porcellio  阅读(509)  评论(0编辑  收藏  举报