动网论坛,站长建站首选,国内使用量最多的论坛软件 动网论坛官方技术讨论区 站长工具 申请属于您自己的免费论坛
首页 | 新闻资讯 | 网站运营 | 网络编程 | 数据库 | 服务器 | 网页设计 | 图像媒体 | 网络应用 | 搜索优化 | 资源下载 | 动网主机 | DVBOX
    本站内  互联网 ASP论坛  ASP.Net论坛  PHP论坛
   Asp → 阅读文章

 将Web页面转换成XML数据源

作者来源: 
阅读 1341 人次 , 2006-2-16 14:30:00 

本文将为你提供了一个强大而灵活的方法,旨在从现有的HTML文件中提取并组合成有意义的数据。

HTML 和Web 已经永远地改变了人们通信与沟通的方式,HTML对人们来说很方便,它使得信息更易于查看和航行,但遗憾的是,它对计算机之间的交流就远远没有那么方便了:Web页面上由于层的实现代码,使得计算机系统都难以找到和使用数据。这时,XML应运而生,它承诺要对计算机系统之间通信的方式起到同样的作用,XML将成为信息在不同计算机系统之间流动的公用语言。应用本文中介绍的简单编程技术,你可以将任何HTML页面转换成一个XML数据源。

例程说明
想象有一个花店,每个星期都要根据价格从3个鲜花批发商中的一个进货。每个星期,店主都要查看每个批发商的Web 站点来找到最低的价格。店主想把这三个批发商的价格信息都组合到一个Web页面中来简化他搜索的过程。

下面就示范如何从3个 Web页面中提取信息并且将它们结合到一个单一的XML文档中。我们为这个例子创建了3个鲜花批发商的页面:

<http://www.azur.com/flowershopdemo/fakeflowers.asp>
<http://www.azur.com/flowershopdemo/fictitiousflowers.asp>
<http://www.azur.com/flowershopdemo/pretendflowers.asp>

出于示范目的,每次访问页面时,每个页面上的价格都会改变。另外,由于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 语言元素:

<!&#151;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事件就被激活。这样一来,即使是导航失败,也能保证这个标志最终会被设置为真,然后我们就退出循环。



现在向类中增加以下函数,以便处理WebGather元语言:

Public Function Transform(ByVal sXML As String) As String
Dim Ntemplates As IXMLDOMNodeList
Dim Ntemplate As IXMLDOMElement
Dim Ntables As IXMLDOMNodeList
Dim Ntable As IXMLDOMElement
Dim Nchild As IXMLDOMElement
Dim Ntext As IXMLDOMText
Dim XMLDOM As DOMDocument
Dim bLoad As Boolean
Dim sValue As String

' Load the template
Set XMLDOM = CreateObject("Microsoft.XMLDOM")
bLoad = XMLDOM.loadXML(sXML)

' Verify you successfully loaded the XML document
If Not bLoad Then
Err.Raise vbObjectError + 1000, _
"DataGather.LoadXMLFromTemplate", _
"Invalid XML"
End If

Set Ntemplates = _
XMLDOM.selectNodes("//WG:Template")

For Each Ntemplate In Ntemplates
bLoad = LoadPage _
(Ntemplate.getAttribute("url"))
Set Ntables = NTemplate.selectNodes _
(".//WG:GetTableElement")

For Each Ntable In Ntables
If bLoad Then
sValue = GetTableCell _
(Ntable.getAttribute("pos"), _
Ntable.getAttribute("row"), _
Ntable.getAttribute("col"))
Else
sValue = "Not Found"
End If

' Create a new text node from the value
Set Ntext = XMLDOM.createTextNode(sValue)

' Replace the current node with
' the new text node
Ntable.parentNode.replaceChild _
Ntext, Ntable
Next

' Remove the template node by assigning all
' its children to the parent node
For Each Nchild In Ntemplate.childNodes
Ntemplate.parentNode.appendChild Nchild
Next
Ntemplate.parentNode.removeChild Ntemplate
Next

' Remove the root document node by
' making the first child the root node
Set XMLDOM.documentElement = _
XMLDOM.documentElement.childNodes(0)
Transform = XMLDOM.xml
End Function

Transform函数在strXML 参数之间反复。每当它遇到一个 Template元素,它就装载URL 属性值所指定的页面,然后用指定表格单元中的数据代替任何子GetTableElement标记。GetTableCell函数在HTML DOM 中反复,直到它找到指定的表格、行和列。

以下是GetTableCell函数:

Private Function GetTableCell(ByVal iTablePos _
As Integer, iRow As Integer, iCol As Integer) _
As String
Dim oElement As Variant
Dim iCount As Integer

On Error GoTo ErrorHandler:

iCount = 1
For Each oElement In _
m_IE.Document.documentElement.All
If UCase(oElement.nodeName) = "TABLE" Then
If iCount = iTablePos Then
GetTableCell = oElement.rows(iRow - _
1).cells(iCol - 1).innerText
Exit Function
End If
iCount = iCount + 1
End If
Next

ErrorHandler:
GetTableCell = "Not Found"
End Function

测试MetaGather 对象
要想测试 MetaGather对象,你可以创建一个ASP页面,用它来处理列表1中的XML文件。页面创建一个WebGather对象,将它传递给XML文档字符串,然后应用一个XSL格式表在浏览器中显示结果。在Web服务器的一个目录中创建一个叫做FlowerShop.asp的ASP页面,可以从浏览器中访问它。下面是FlowerShop.asp的内容:

<% @Language=VBScript %>
<% Option Explicit %>
<% Response.Expires = 1 %>

<html>
<body>
<h1>Vendor Price Comparison</h1>
<%
' Generate the price comparison table
Dim oDataGather, strXML, oXMLDOM, oXSLDOM

' Load the template file that specifies
' how to gather information
Set oXMLDOM = _
Server.CreateObject("Microsoft.XMLDOM")
oXMLDOM.async = False
oXMLDOM.Load Server.MapPath("Flowers.xml")

' Pass the XML as a string to the DataGather class
Set oDataGather = _
Server.CreateObject("WebGather.XMLMetaGather")
strXML = oDataGather.Transform(oXMLDOM.xml)
Set oDataGather = Nothing

' Load the returned XML into an XMLDOM
'so you can apply an XSL stylesheet
oXMLDOM.LoadXML strXML

' Load the XSL stylesheet
Set oXSLDOM = _
Server.CreateObject("Microsoft.XMLDOM")
oXSLDOM.async = False
oXSLDOM.Load Server.MapPath("Flowers.xsl")

' Apply the XSL and write the result
Response.Write oXMLDOM.transformNode(oXSLDOM)

' Clean up
Set oXMLDOM = Nothing
Set oXSLDOM = Nothing
%>
<B>Press the Refresh Button to get current
prices from the vendor sites.</B>
</body>
</html>

这个ASP页面要引用另外两个页面:Flower.xml和Flowers.xsl。 这些文件必须与ASP页面位于Web 服务器的同一个目录下。列表1包含了Flower.xml文件,列表2是Flowers.xsl的内容,它将生成的XML转换成适合在浏览器中显示的HTML表格:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match = "/">
<table border="1"> <tr> <th>Vendor</th> <th>Flower</th> <th>Price</th> </tr> <xsl:for-each select="//Flowers/Flower"> <tr> <td><xsl:value-of select="Vendor"/></td> <td><xsl:value-of select="Name"/></td> <td><xsl:value-of select="Price"/></td> </tr> </xsl:for-each> </table> </xsl:template>
</xsl:stylesheet>

当浏览FlowerShop.asp页面时,你会看到一个表格,它显示了来自三个不同批发商站点的水仙花价格。你可以访问以下地址查看本文整个例子的工作演示:http://www.azur.com/flowershopdemo。

建立功能更加强大的解决方案
本文所描述的方法对于内容相对稳定的Web站点是行之有效的,要修改更加动态的Web页面则需要一个更加复杂的方案。可以编写代码,通过查找特定的文本或选择一个完整表格中的内容来扩展选择值,但是如果Web页面的结构改变了,一些非常简单的算法都将被打破。

如果考虑实施更为复杂的方案。可以考虑AZUR (www.azur.com) 的产品eClips,我们可以使用同样的但却是更加先进的技术来监控动态改变的内容。eClips使用一个拖放界面监控选中的元素,当该元素改变时将进行警告,直接向移动设备发布信息更新,跟踪选中值的历史记录。eClips允许任何Web页面都成为一个XML数据源。

  
 
 收藏本文  打印本文  论坛讨论  关闭窗口
· 上一篇:微软建议的ASP性能优化28条守则
· 下一篇:XML与面向Web的数据挖掘技术
· 常用的 ASP ActiveX 组件
· ASP Chart 简要介绍
· 页面之间传递元素的办法
· Asp的安全管理(1)
· remote script文档(转载自微软)(六)


关于本站 | 联系我们 | 业务合作 | 客户案例 | 诚聘英才 | 广告合作 | 收藏本站
海口动网先锋网络科技有限公司版权所有
Copyright © 2000 - 2006 Cndw.Com
中华人民共和国电信与信息服务业务经营许可证编号 琼 ICP 020077