位置:海鸟网 > IT > ASP.NET >

将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>Fake Flowers</Vendor><Name>Daffodil</Name>
<Price>$2.00</Price></Flower>
<Flower><Vendor>Fictitious Flowers</Vendor><Name>Daffodil</Name><Price>$5.00</Price>
</Flower>
<Flower><Vendor>Pretend Flowers</Vendor>
<Name>Daffodil</Name><Price>$3.50</Price></Flower>
</Flowers>


现在你需要编写代码,直接从相应的批发商Web 站点中提取鲜花的名称和价格。一个解决方案是在XML 文档中放置特殊的标记,以后用站点中的值来代替。这种方法与 XSL相同。要想这样做,你可以定义一个新的元语言,它可让你向XML中增加可替换的标记。
这个新的元语言需要完成以下任务:

识别文档,以便知道它是在使用这个语言
提供一个方法,以指定包含着你想恢复数据的Web页面
指定如何从每个页面恢复特定的数据元素。下面的例子提取前一个XML文件,并且包含了新的元语言标记来完成上面所列举的3个目标:
<WG:Document xmlns:WG="http://www.azur.com/FlowerShopDemo/WebGatherSchema.xml" >
<Flowers>
<WG:Template url="http://www.azur.com/flowershopdemo/fakeflowers.asp">
<Flower>
<Vendor>Fake Flowers</Vendor>
<Name><WG:GetTableElement pos="1" row="8" col="1"/></Name>
<Price><WG:GetTableElement pos="1" row="8" col="4"/></Price>
</Flower>
</WG:Template>
<WG:Template url="http://www.azur.com/flowershopdemo/fictitiousflowers.asp">
<Flower>
<Vendor>Fictitious Flowers</Vendor>
<Name><WG:GetTableElement pos="1" row="6" col="2"/></Name>
<Price><WG:GetTableElement pos="1" row="6" col="3"/></Price>
</Flower>
</WG:Template>
<WG:Template url="http://www.azur.com/flowershopdemo/pretendflowers.asp">
<Flower>
<Vendor>Pretend Flowers</Vendor>
<Name><WG:GetTableElement pos="1" row="3" col="1"/></Name>
<Price><WG:GetTableElement pos="1" row="3" col="4"/></Price>
</Flower>
</WG:Template>
</Flowers>
</WG:Document>

第二个XML例子有一个包裹元素叫做 Document,放置在原始XML的两头。Document元素为这个叫做WebGather的新元语言定义了名称空间。 WebGatherSchema.xml文件中定义了WebGather 语言元素:

<!—WebGather schema -->
<Schema xmlns="urn:schemas-microsoft-com:xml-data" >
<element type='Document'>
<element type='Template'>
<attribute type='url'/>
<element type='GetTableElement'>
<attribute type='pos'/>
<attribute type='row'/>
<attribute type='col'/>
</element>
</element>
</element>
</Schema>

WebGather schema允许使用三种类型的XML元素:Template(模板)元素只有一个属性 "URL",它定义了包含数据的源Web页面。GetTableElement标记是一个在Template元素中定义的页面内表格中一个单元的内容占位符。GetTableElement标记有三个属性,第一个属性叫做"pos" ,它定义了HTML Web 页面中表格元素的索引号,其中第一个表格就是1;"row"和"col"属性定义了包含数据的表格中的单元。

具体实现
元语言需要执行才能起作用。我使用了一个 Visual Basic DLL工程文件,其中只包含了一个类叫做MetaGather。这个类使用了一个公共方法,叫做Transform,它接收一个 XML 字符串,其中包含WebGather标记,它取代带有来自指定Web 页面值的那些标记,生成XML 字符串。这个类使用了Microsoft InternetExplorer控件来恢复Web 页面,并从XML字符串参数中的Template 标记中读取包含数据的页面URL。

Private Function LoadPage _
(ByVal strURL As String) As Boolean
' Initialize the download complete flag
m_bDownloadComplete = False

' Load the page to make sure its
' not the cached version
m_IE.Navigate strURL, 4

' Wait until document finishes loading
While m_IE.ReadyState <> READYSTATE_COMPLETE
DoEvents
Wend

' Check if you ended up on the error page
If m_IE.Document.Title = _
"The page cannot be found" Or _
m_IE.Document.Title = "No page to display" _
Then
LoadPage = False
Else
LoadPage = True
End If
End Function

LoadPage 函数调用Microsoft Internet控件的Navigate方法从Internet中取回页面内容。Navigate工作方式是不同步的,因此在继续之前必须要等待页面装载。这可以通过使用一个循环以等待一个模块级别的标志设置完成来实现。DownloadComplete事件被激活时,这个标志就被设置。通常Navigate 方法被调用时,DownloadComplete事件就被激活。这样一来,即使是导航失败,也能保证这个标志最终会被设置为真,然后我们就退出循环。