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++项目设为启动项即可.