国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java 實踐: 用 XQuery 進行屏幕搜集

2019-11-18 13:09:51
字體:
來源:轉載
供稿:網友

  上個月,java 技術講師 Sam Pullara 向我演示了他最新的支持 Java 的電話 Nokia 6630。這個手機使用了全面的技術 —— 嵌入式 JVM、GPRS 和藍牙,但是它也遭遇了所有智能手機都苦惱的問題 —— 有限的屏幕實際使用區。有些 Web 站點支持基于手機的瀏覽器,而且嵌入式瀏覽器也試圖在小小的屏幕上有效地渲染頁面,但是,在電話屏幕上查看典型的 Web 頁面,就像要把一頭大象強行塞進車后座一樣(其中的每個參與者都會感到失望,包括您、車和大象)。Sam 構建了一個簡單的、優雅的解決方案,從他喜歡的 Web 站點上對數據進行屏幕搜集,然后把數據重新格式化,在小屏幕上顯示。
  
  新方法
  從 Html 文檔提取數據的方法有許多種,但是我真的很喜歡 Sam 采用的方法:既把 XQuery 當作屏幕搜集工具(從頁面中提取相當的數據),又把它當作樣式表工具(重新格式化數據,以便數據適應頁面,不需要進行頁面滾動)。只要少量基礎設施和一些非常簡單的 XQuery 表達式,就可以從大量數據源提取出相關數據 —— 例如交通、天氣和財務報價等,并在電話上完好地顯示數據。
  
  我過去經常處于這種情況:對 HTML 頁面進行屏幕搜集對某些特定問題來說似乎是可行的方案,但是幾乎沒有用于屏幕搜集的 Java 工具包。有許多 HTML 解析工具,但它們通常缺少足夠的抽象能力(把屏幕搜集代碼弄得亂七八糟),大量不符合 HTML 規范的應用限制了它們,它們也無法處理那些結構可能隨時間發生變化的、動態生成的頁面。
  
  為了彌補質量低下的 HTML 和豐富的 xml 處理工具之間的空白,首先要把 HTML 轉換成 XML。許多工具有助于完成這項工作;JTidy 工具包做得很好,可以使這項工作變得輕松一些。JTidy 的設計目標是讀入典型質量(即很糟)的 HTML 并輸出更整潔的結果(有選項可供選擇),它還提供了一個 DOM 接口,用來遍歷能夠發送給 XML 解析器的 HTML 文檔。清單 1 中的代碼將從 InputStream 中讀取 HTML 文檔,并生成文檔的 DOM 表示:
  
  清單 1. 用 JTidy 把 HTML 轉換成 XML 兼容的 DOM
  
  Tidy tidy = new Tidy();
  tidy.setQuiet(true);
  tidy.setShowWarnings(false);
  Document tidyDOM = tidy.parseDOM(inputStream, null);
  
  用這個簡單的轉換,就差不多能把每個 Web 頁面都當作 XML 文檔進行處理,還能用自己喜歡的任何 XML 工具(比如 SAX、XSL、XPath,等等)提取數據。雖然 XSL 可能是很明智的選擇(因為其設計目標就是為了從 XML 文檔中提取信息并轉換這些信息,以便顯示它們),但是假如不了解 XSL 的話,它的學習曲線就很難把握,即使是最簡單的 XSL 轉換也復雜得讓人心煩。XPath 是處理信息提取的一個好選擇 —— XSL 和 XQuery 都用它進行內容選擇,可以很輕易地使用 XPath 把需要的數據提取出來,然后對 HTML 進行格式化,但是 XQuery 會讓這項工具更加輕易。
  
  XQuery:簡介
  
  XQuery 的設計目標是從可能非常大的 XML 數據集中提取數據。輸入的數據集不必是 XML 文檔,雖然它可能是 XML 文檔,但是也可能是已經編入索引并保存在 XML 數據庫中的文檔集合,甚至是一組關系數據庫中的表。像 SQL 一樣,XQuery 包含從多個數據集中提取數據、匯總數據、聚合數據和連接數據的函數。
  
  就像 jspasp 或 Velocity 這樣的表示性模板語言一樣,XQuery 把兩個域(表示域和計算域)中的元素組合成一種組合語法。結果,所有 XML 文檔都自動成為有效的 XQuery 表達式,并對自身進行評估。XQuery 還包含一些語言語句(language statement),例如“for”和“let”,它們可以與 XML 元素混合使用。
  
  清單 2 顯示了一個示例 XML 文檔 bib.xml,它表示一個書目。然后我們將介紹一些快速的 XQuery 表達式,讓您對 XQuery 能夠做什么形成一種熟悉,最后我們將再轉到屏幕搜集的示例上。要全面介紹 XQuery 的語法和使用情況可能要用幾百頁的篇幅,有關更具體的參考材料和示例,請參閱 參考資料 小節。
  
  清單 2. 示例 XML 書目
  
  <bib>
  <book year="1994">
    <title>TCP/ip Illustrated</title>
    <author><last>Stevens</last><first>W.</first></author>
    <publisher>Addison-Wesley</publisher>
    <price> 65.95</price>
  </book>
  . . . more books . . .
  </bib>
  
  清單 3 顯示了一個 XQuery 表達式,它選擇 Addison-Wesley 在 1991 年以后出版的所有書籍,提取它們的標題,并把標題格式化成前面有項目符號的(<ul>)列表。大括號表示從“表示模式”(數據直接傳遞到輸出 ,例如 <ul> 和 <li> 標簽)到“代碼模式”的切換;然后在 return 子句之后立即進行從“代碼模式”到“表示模式”的隱式切換。
  
  清單 3. 根據查詢參數選擇圖書標題的 XQuery 表達式
  
  <ul>
  {
   for $b in doc("bib.xml")/bib/book
   where $b/publisher = "Addison-Wesley" and $b/@year > 1991
   return
  <li>{ data($b/title) }</li>
  }
  </ul>
  
  查詢語法引入了“for”,通常稱之為“Flower 表達式”(來自 FLWOR,是 for-let-where-order-return 的縮寫),該語法從文檔中選擇一系列 XML 節點,在該例中,用 XPath 選取了來自 bib.xml 文檔的 <book> 節點集,然后進一步過濾出與指定查詢參數(出版商是 Addison-Wesley,出版日期是 1991 年之后)匹配的節點。對于選出的每個節點,將在 return 子句中計算表達式,在這里是標記(<li> 標簽)與代碼(提取出每個 <book> 節點的 <title> 元素的內容)的混合。
  
  這個簡單的 XQuery 示例描述了 XQuery 的幾個方面 —— 某一文檔中表示與代碼的混合、XPath 的運用、子條件的運用($b 引用)、非凡的查詢表達式、XQuery 函數(data()),還有一個事實:輸出文檔的結構不必與輸入文檔的結構匹配。就在這個相當緊湊的、讀起來不是很難的查詢中,孕育著強大的處理能力。
  
  清單 4 顯示了一個更簡單的 XQuery 表達式,它把書目中不同出版商的數量,在一個 <count> 元素中輸出。像前一個示例一樣,它用 XPath 表達式選擇一組節點,然后用 XQuery 函數選擇惟一值,并計算節點的數量。它通過運算獲得一個數字 —— bib.xml,即文檔中不同出版商的數量。
  
  清單 4. 計算不同出版商數量的 XQuery 表達式
  
  <count>
  {
   let $d := distinct-values(doc("bib.xml")/book/publisher)
   return count($d)
  }
  </count>
  
  這些示例只是 XQuery 能夠執行的各種查詢類型的很少一部分,提供這些例子僅僅是為了讓您對使用 XQuery 能夠做的事情有些感覺,以及提示您如何才能用 XQuery 把 XML 文檔轉換成自己選擇的格式。雖然 XQuery 的大部分功能主要用于查詢大型文檔或者其他數據源,但是也可以使用 XQuery 非常簡單的子集來對 HTML 文檔進行屏幕搜集,為各種應用程序提取出需要的數據,例如在屏幕大小有限的設備(例如蜂窩電話)上顯示有關的數據,或者創建一個 DIY 的門戶網站,聚集并顯示來自多個站點的數據。
  
  用 XQuery 進行屏幕搜集
  
  對 Web 頁面做屏幕搜集的許多挑戰之一是:它們通常沒有可以自我標識的結構,而且它們的結構可能隨著站點內容的編輯而變化,甚至有可能根據不同的請求,在頁面中插入不同的動態內容(例如廣告內容)。因此,對于頁面中哪一部分的內容與要提取的數據相對應,通常不得不進行猜測。
  
  股票價格
  
  現在,讓我們從提取 Yahoo! 財經頁面中 IBM 股票的當前價格開始(http://finance.yahoo.com/q?s=IBM)。這個頁面上有許多材料 —— 新聞標題、廣告、財經數據,等等,但是我想要的是股票的價格數據,它放在一個表格單元格中,靠近包含“Last Trade”的單元格。清單 5 中的查詢語句將選擇所有文本內容中包含“Last Trade”的 <td> 節點,然后為每個節點(希望只有一個)輸出一個包含后續<td> 節點內容的表格行。內容是用 return 子句中的 data() 函數提取的;否則,不僅僅會得到 <td> 節點中的文本,還會得到所有的標記。(在這個查詢中,惟一包含技巧的部分是 text()[1] 這個部分;在這里,text() 函數匹配的是 <td> 元素中的所有元素 —— 在這個例子只有一個元素,但 XQuery 并不知道這一點 —— 所以必須進一步告訴它在進行文本匹配之前,必須選擇第一個文本節點)。只要頁面包含一個表格單元格的文本是“Last Trade”,而且后續的單元格包含的是股票價格,那么,即使頁面的結構隨意變化,也不會造成查詢失敗。
  
  清單 5. 從 Yahoo! 財經提取股票報價的 XQuery 表達式
  
  <table>
  {
   for $d in //td
   where contains($d/text()[1], "Last Trade")
   return <tr><td> { data($d/following-sibling::td) } </td></tr>
  }
  </table>
  
  天氣
  
  現在來試一下另外一個頁面。Yahoo! 天氣頁面包含許多 portlet 面板,我想提取上面所列城市的名稱、溫度和圖標。(假如登錄 Yahoo! 天氣頁面 http://weather.yahoo.com,則屏幕上會顯示出在“我的 Yahoo!”中所選城市的天氣,否則會顯示一些主要大城

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 炉霍县| 灵寿县| 苍梧县| 阿合奇县| 神农架林区| 南投县| 永宁县| 阿拉善左旗| 湘潭县| 噶尔县| 古浪县| 富宁县| 高要市| 东台市| 海兴县| 武定县| 泰州市| 隆德县| 白城市| 洪洞县| 隆回县| 镇雄县| 巴林右旗| 钟祥市| 宣武区| 静海县| 太白县| 北票市| 东丽区| 菏泽市| 舒城县| 蒲江县| 商城县| 五大连池市| 年辖:市辖区| 鹤庆县| 垫江县| 阳春市| 湛江市| 东方市| 烟台市|