跳轉到內容

XQuery/BBC 天氣預報

來自華夏公益教科書,開放書籍,開放世界

BBC 天氣預報

[編輯 | 編輯原始碼]

BBC 提供一些天氣資料,以 RSS 形式提供。目前,這包括 當前狀況3 天預報。由於缺少天氣屬性的標準標籤集,狀況以字串形式表示,需要進行字串解析才能訪問元素資料。

對於其他預報,例如 24 小時和 5 天預報,這些預報不以 RSS 形式提供,因此我們必須抓取 HTML 頁面。

完成此任務的一種方法是使用這個 雅虎管道,它將頁面轉換為 RSS 提要。但是,將資料轉換為 XML 元素會更有用。

日期和時間

[編輯 | 編輯原始碼]

在所有這些頁面和提要中,都存在一個問題,即為預報或觀測分配日期。日期經常被省略或表示為星期幾。這會導致處理 RSS 和 HTML 頁面時出現複雜情況。

24 小時預報

[編輯 | 編輯原始碼]

此指令碼使用 eXist 模組 httpclient 獲取 HTML,解析 HTML 並生成 XML 檔案。然後,可以透過 XSLT 將此 XML 轉換為可檢視的頁面。


此指令碼有兩個引數

  • region - 必填 - BBC 獨有的數字程式碼(?程式碼列表)
  • area - 可選 - 子區域,通常是郵政編碼的開頭
declare namespace h ="http://www.w3.org/1999/xhtml";

declare function local:day-of-week($date) {
    ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
       [  xs:integer(($date - xs:date('1901-01-06'))
          div xs:dayTimeDuration('P1D')) mod 7
        +1]
};

let $area := request:get-parameter("area",())
let $region := request:get-parameter("region","2")
let $url := concat ("http://news.bbc.co.uk/weather/forecast/",$region, "?state=fo:B", if (exists($area)) then concat("&area=",$area)  else ())
let $doc := httpclient:get(xs:anyURI($url),false(),())
let $currentDate := current-date()
let $currentTime := current-time()
let $dow := local:day-of-week($currentDate)
return
element forecasts {
          element region {$region},
          if (exists($area)) then element area {$area} else () ,
          element source {"BBC"},
  for $row in  $doc/httpclient:body//h:table/h:tbody/h:tr
  let $raw-time :=normalize-space($row/h:td[1])
  let $time := if (contains($raw-time," ")) then substring-before($raw-time," ") else $raw-time
  let $time := xs:time(concat($time,":00"))
  let $pdow := if (contains($raw-time,"(")) then substring-before(substring-after($raw-time,"("),")") else $dow
  let $date := if ($pdow ne $dow)   then $currentDate + xs:dayTimeDuration("P1D") else $currentDate
   return 
      element forecast {
         element date {$date},
         element time {$time},
         element dow {$pdow},
         element summary {string($row/h:td[2]//h:p[@class="sum"])},
         element imageurl {string($row/h:td[2]//h:div[@class="summary"]//h:img/@src)},
         element maxTemp{ attribute units {"degc"} , $row/h:td[3]//h:span[@class="cent"]/text()},
         element maxTemp {attribute units {"degf"} , $row/h:td[3]//h:span[contains(@class,"fahr")]/text()},
         element windDirection {string($row/h:td[4]//h:span[contains(@class,"wind")]/@title)},
         element windSpeed {attribute units {"mph"} , substring-before($row/h:td[4]//h:span[contains(@class,"mph")], "mph")},
         element windSpeed {attribute units {"kph"} ,substring-before($row/h:td[4]//h:span[contains(@class,"kph")], "km/h")},
         element humidity {attribute units {"%"}, normalize-space(substring-before($row/h:td[5]//h:span[contains(@class,"hum")], "%"))},
         element pressure  { attribute units {"mb"} , normalize-space(substring-before($row/h:td[5]//h:span[@class="pres"], "mB"))},
         element visibility {normalize-space($row/h:td[5]//h:span[contains(@class,"vis")])}
       }
}

布里斯托爾的 24 小時預報

華夏公益教科書