XQuery/BBC 天氣預報
外觀
< XQuery
BBC 提供一些天氣資料,以 RSS 形式提供。目前,這包括 當前狀況 和 3 天預報。由於缺少天氣屬性的標準標籤集,狀況以字串形式表示,需要進行字串解析才能訪問元素資料。
對於其他預報,例如 24 小時和 5 天預報,這些預報不以 RSS 形式提供,因此我們必須抓取 HTML 頁面。
完成此任務的一種方法是使用這個 雅虎管道,它將頁面轉換為 RSS 提要。但是,將資料轉換為 XML 元素會更有用。
在所有這些頁面和提要中,都存在一個問題,即為預報或觀測分配日期。日期經常被省略或表示為星期幾。這會導致處理 RSS 和 HTML 頁面時出現複雜情況。
此指令碼使用 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")])}
}
}