web|xml|数据|数据源|页面|转换
本文将为你提供了一个强大而灵活的方法旨在从现有的HTML文件中提取并组合成有意义的数据。
HTML和Web已经永远地改变了人们通信与沟通的方式HTML对人们来说很方便它使得信息更易于查看和航行但遗憾的是它对计算机之间的交流就远远没有那么方便了Web页面上由于层的实现代码使得计算机系统都难以找到和使用数据。这时XML应运而生它承诺要对计算机系统之间通信的方式起到同样的作用XML将成为信息在不同计算机系统之间流动的公用语言。应用本文中介绍的简单编程技术你可以将任何HTML页面转换成一个XML数据源。
例程说明
想象有一个花店每个星期都要根据价格从3个鲜花批发商中的一个进货。每个星期店主都要查看每个批发商的Web站点来找到最低的价格。店主想把这三个批发商的价格信息都组合到一个Web页面中来简化他搜索的过程。
下面就示范如何从3个Web页面中提取信息并且将它们结合到一个单一的XML文档中。我们为这个例子创建了3个鲜花批发商的页面
<>
<>
<>
出于示范目的每次访问页面时每个页面上的价格都会改变。另外由于Web页面经常会把相关数据放在HTML表格中样本页面和应用程序将着重从表格中而不是从其它标记中恢复信息。
解决方案
下表包含了一个含有你需要的数据的样本XML文件Flowers.xml
<Flowers><Flower><Vendor>FakeFlowers</Vendor><Name>Daffodil</Name>
<Price>$2.00</Price></Flower>
<Flower><Vendor>FictitiousFlowers</Vendor><Name>Daffodil</Name><Price>$5.00</Price>
</Flower>
<Flower><Vendor>PretendFlowers</Vendor>
<Name>Daffodil</Name><Price>$3.50</Price></Flower>
</Flowers>
现在你需要编写代码直接从相应的批发商Web站点中提取鲜花的名称和价格。一个解决方案是在XML文档中放置特殊的标记以后用站点中的值来代替。这种方法与XSL相同。要想这样做你可以定义一个新的元语言它可让你向XML中增加可替换的标记。
这个新的元语言需要完成以下任务
识别文档以便知道它是在使用这个语言
提供一个方法以指定包含着你想恢复数据的Web页面
指定如何从每个页面恢复特定的数据元素。下面的例子提取前一个XML文件并且包含了新的元语言标记来完成上面所列举的3个目标
<WG:Documentxmlns:WG="">
<Flowers>
<WG:Templateurl="">
<Flower>
<Vendor>FakeFlowers</Vendor>
<Name><WG:GetTableElementpos="1"row="8"col="1"/></Name>
<Price><WG:GetTableElementpos="1"row="8"col="4"/></Price>
</Flower>
</WG:Template>
<WG:Templateurl="">
<Flower>
<Vendor>FictitiousFlowers</Vendor>
<Name><WG:GetTableElementpos="1"row="6"col="2"/></Name>
<Price><WG:GetTableElementpos="1"row="6"col="3"/></Price>
</Flower>
</WG:Template>
<WG:Templateurl="">
<Flower>
<Vendor>PretendFlowers</Vendor>
<Name><WG:GetTableElementpos="1"row="3"col="1"/></Name>
<Price><WG:GetTableElementpos="1"row="3"col="4"/></Price>
</Flower>
</WG:Template>
</Flowers>
</WG:Document>
第二个XML例子有一个包裹元素叫做Document放置在原始XML的两头。Document元素为这个叫做WebGather的新元语言定义了名称空间。WebGatherSchema.xml文件中定义了WebGather语言元素
<!WebGatherschema-->
<Schemaxmlns="urn:schemas-microsoft-com:xml-data">
<elementtype='Document'>
<elementtype='Template'>
<attributetype='url'/>
<elementtype='GetTableElement'>
<attributetype='pos'/>
<attributetype='row'/>
<attributetype='col'/>
</element>
</element>
</element>
</Schema>
WebGatherschema允许使用三种类型的XML元素Template模板元素只有一个属性"URL"它定义了包含数据的源Web页面。GetTableElement标记是一个在Template元素中定义的页面内表格中一个单元的内容占位符。GetTableElement标记有三个属性第一个属性叫做"pos"它定义了HTMLWeb页面中表格元素的索引号其中第一个表格就是1"row"和"col"属性定义了包含数据的表格中的单元。
具体实现
元语言需要执行才能起作用。我使用了一个VisualBasicDLL工程文件其中只包含了一个类叫做MetaGather。这个类使用了一个公共方法叫做Transform它接收一个XML字符串其中包含WebGather标记它取代带有来自指定Web页面值的那些标记生成XML字符串。这个类使用了MicrosoftInternetExplorer控件来恢复Web页面并从XML字符串参数中的Template标记中读取包含数据的页面URL。
PrivateFunctionLoadPage_
(ByValstrURLAsString)AsBoolean
'Initializethedownloadcompleteflag
m_bDownloadComplete=False
'Loadthepagetomakesureits
'notthecachedversion
m_IE.NavigatestrURL,4
'Waituntildocumentfinishesloading
Whilem_IE.ReadyState<>READYSTATE_COMPLETE
DoEvents
Wend
'Checkifyouendedupontheerrorpage
Ifm_IE.Document.Title=_
"Thepagecannotbefound"Or_
m_IE.Document.Title="Nopagetodisplay"_
Then
LoadPage=False
Else
LoadPage=True
EndIf
EndFunction
LoadPage函数调用MicrosoftInternet控件的Navigate方法从Internet中取回页面内容。Navigate工作方式是不同步的因此在继续之前必须要等待页面装载。这可以通过使用一个循环以等待一个模块级别的标志设置完成来实现。DownloadComplete事件被激活时这个标志就被设置。通常Navigate方法被调用时DownloadComplete事件就被激活。这样一来即使是导航失败也能保证这个标志最终会被设置为真然后我们就退出循环。