重要 API
使用 Windows.Web.Syndication 命名空間中的功能,利用依據 RSS 與 Atom 標準產生的聯播摘要,擷取或建立最新且最熱門的 Web 內容。
Note
Windows.Web.Syndication這些 Windows.Web.AtomPub API 是 Windows 執行階段(WinRT)API,能在 WinUI 3(Windows 應用程式 SDK)桌面應用程式以及 UWP 應用程式中使用。
什麼是餵食?
網路摘要是包含任意數量的個別項目的文件,而這些項目由文字、連結和圖片組成。 對動態消息的更新是以新條目的形式進行,用以推廣網路上的最新內容。 內容消費者可以使用訂閱閱讀應用程式,彙整並監控來自多位個別內容作者的訂閱源,快速且方便地取得最新內容。
支援哪些訂閱格式標準?
Windows 支援擷取符合 RSS 0.91 到 RSS 2.0 格式標準,以及 Atom 0.3 到 1.0 標準的摘要資訊。 Windows.Web.Syndication 命名空間中的類別可定義能同時表示 RSS 和 Atom 元素的摘要來源和摘要項目。
此外,Atom 1.0 與 RSS 2.0 格式都允許其訂閱文件包含官方規範中未定義的元素或屬性。 隨著時間推移,這些自訂元素與屬性已成為定義其他網路服務資料格式(如 GData 和 OData)所使用的領域專屬資訊的方式。 為了支援這項新增功能, SyndicationNode 類別代表通用的 XML 元素。 使用 SyndicationNode 搭配 Windows.Data.Xml.Dom 命名空間中的類別,可讓應用程式存取其可能包含的屬性、擴充功能及任何內容。
請注意,針對聯合發行內容,Windows 實作的 Atom 出版協定(Windows.Web.AtomPub)僅依照 Atom 及 Atom Publication 標準支援訂閱內容操作。
使用聯播內容並進行網路隔離
Windows 的網路隔離功能讓開發者能夠控制並限制 Windows 應用程式的網路存取。 並非所有應用程式都需要存取網路。 然而,對於那些具備這些功能的應用程式,Windows 提供了不同層級的網路存取權限,並可透過選擇適當的功能來啟用。
網路隔離讓開發者能為每個應用程式定義所需的網路存取範圍。 未定義適當範圍的應用程式將無法存取指定類型的網路,以及特定類型的網路請求(如由用戶端發起的外部請求,或同時包含非請求請求與用戶端發起的外部請求)。 設定並執行網路隔離的能力確保若應用程式遭到入侵,只能存取該應用程式明確授權的網路。 這大大減少了對其他應用程式及 Windows 的影響範圍。
網路隔離會影響 Windows.Web.Syndication 和 Windows.Web.AtomPub 命名空間中任何嘗試存取網路的類別。 Windows 會積極執行網路隔離。 如果未啟用適當的網路功能,對 Windows.Web.Syndication 或 Windows.Web.AtomPub 命名空間中類別元素的呼叫在導致網路存取時,可能會因網路隔離而失敗。
應用程式的網路能力會在應用程式建置時的應用程式清單中設定。 網路功能通常會在開發應用程式時使用 Visual Studio 加入。 網路能力也可透過應用程式清單檔案的文字編輯器手動設定。
欲了解更多關於網路隔離與網路能力的詳細資訊,請參閱 網路基礎 主題中的「能力」章節。
如何存取網站摘要
本節說明如何在以 C# 撰寫的 Windows 應用程式中,使用 Windows.Web.Syndication 命名空間中的類別來擷取並顯示 Web 摘要。
先決條件
為了確保您的 Windows 應用程式具備網路支援,您必須在專案 Package.appxmanifest 檔案中設定所需的網路能力。 如果你的應用程式需要以客戶端身份連接到網際網路上的遠端服務,那麼 internetClient 功能就很重要。 欲了解更多資訊,請參閱 網路基礎 主題中的「能力」部分。
從 Web 摘要來源擷取彙整內容
現在我們將回顧一些程式碼,示範如何擷取訂閱源,並顯示該訂閱源中包含的每一項項目。 在設定並傳送請求之前,我們會先定義幾個操作中會使用的變數,並初始化一個 SyndicationClient 實例,該實例定義了我們用來擷取和顯示資料流的方法與屬性。
如果傳給建構子的 uriString 不是有效的 URI,Uri 建構子會拋出例外。 所以我們用 try/catch 區塊來驗證 uriString 。
Windows.Web.Syndication.SyndicationClient client = new Windows.Web.Syndication.SyndicationClient();
Windows.Web.Syndication.SyndicationFeed feed;
// The URI is validated by catching exceptions thrown by the Uri constructor.
Uri uri = null;
// Use your own uriString for the feed you are connecting to.
string uriString = "";
try
{
uri = new Uri(uriString);
}
catch (Exception ex)
{
// Handle the invalid URI here.
}
Note
本文中的 JavaScript 範例使用 WinJS(Windows Library for JavaScript),這是 UWP JavaScript 應用程式的舊框架。 這些範例僅供參考,不建議用於新應用程式開發。
var currentFeed = null;
var currentItemIndex = 0;
var client = new Windows.Web.Syndication.SyndicationClient();
// The URI is validated by catching exceptions thrown by the Uri constructor.
var uri = null;
try {
uri = new Windows.Foundation.Uri(uriString);
} catch (error) {
WinJS.log && WinJS.log("Error: Invalid URI");
return;
}
接著我們透過設定所需的伺服器憑證( ServerCredential 屬性)、代理憑證( ProxyCredential 屬性)和 HTTP 標頭( SetRequestHeader 方法)來設定請求。 在基本請求參數設定完成後,會建立一個有效的 Uri 物件,該物件是使用 App 提供的 feed URI 字串所建立。 接著將 Uri 物件傳給 RetrieveFeedAsync 函式以請求資料流。
假設回傳了所需的訂閱內容,範例程式碼會遍歷每個訂閱源項目,呼叫 displayCurrentItem (接下來定義它),透過介面以清單形式顯示項目及其內容。
當你呼叫大多數非同步網路方法時,必須寫程式碼來處理異常。 你的例外處理者可以取得更詳細的異常原因資訊,以更好理解失敗原因並做出適當決策。
如果無法與 HTTP 伺服器建立連線,或 Uri 物件未指向有效的 AtomPub 或 RSS 訂閱源,RetrieveFeedAsync 方法會拋出例外。 JavaScript 範例程式碼使用 onError 函式來捕捉任何異常,並在錯誤發生時列印出更詳細的例外資訊。
try
{
// Although most HTTP servers do not require User-Agent header,
// others will reject the request or return a different response if this header is missing.
// Use the setRequestHeader() method to add custom headers.
client.SetRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
feed = await client.RetrieveFeedAsync(uri);
// Retrieve the title of the feed and store it in a string.
string title = feed.Title.Text;
// Iterate through each feed item.
foreach (Windows.Web.Syndication.SyndicationItem item in feed.Items)
{
displayCurrentItem(item);
}
}
catch (Exception ex)
{
// Handle the exception here.
}
function onError(err) {
WinJS.log && WinJS.log(err, "sample", "error");
// Match error number with an ErrorStatus value.
// Use Windows.Web.WebErrorStatus.getStatus() to retrieve HTTP error status codes.
var errorStatus = Windows.Web.Syndication.SyndicationError.getStatus(err.number);
if (errorStatus === Windows.Web.Syndication.SyndicationErrorStatus.invalidXml) {
displayLog("An invalid XML exception was thrown. Please make sure to use a URI that points to a RSS or Atom feed.");
}
}
// Retrieve and display feed at given feed address.
function retreiveFeed(uri) {
// Although most HTTP servers do not require User-Agent header,
// others will reject the request or return a different response if this header is missing.
// Use the setRequestHeader() method to add custom headers.
client.setRequestHeader("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
client.retrieveFeedAsync(uri).done(function (feed) {
currentFeed = feed;
WinJS.log && WinJS.log("Feed download complete.", "sample", "status");
var title = "(no title)";
if (currentFeed.title) {
title = currentFeed.title.text;
}
document.getElementById("CurrentFeedTitle").innerText = title;
currentItemIndex = 0;
if (currentFeed.items.size > 0) {
displayCurrentItem();
}
// List the items.
displayLog("Items: " + currentFeed.items.size);
}, onError);
}
在前一步, RetrieveFeedAsync 回傳了所請求的訂閱內容,範例程式碼開始迭代可用的訂閱內容。 每個項目皆以 SyndicationItem 物件表示,該物件包含相關聯播標準(RSS 或 Atom)所提供的所有項目屬性與內容。 以下範例中,我們觀察 displayCurrentItem 函式如何透過每個項目工作,並透過各種命名的 UI 元素顯示其內容。
private void displayCurrentItem(Windows.Web.Syndication.SyndicationItem item)
{
string itemTitle = item.Title == null ? "No title" : item.Title.Text;
string itemLink = item.Links == null ? "No link" : item.Links.FirstOrDefault().ToString();
string itemContent = item.Content == null ? "No content" : item.Content.Text;
//displayCurrentItem is continued below.
function displayCurrentItem() {
var item = currentFeed.items[currentItemIndex];
// Display item number.
document.getElementById("Index").innerText = (currentItemIndex + 1) + " of " + currentFeed.items.size;
// Display title.
var title = "(no title)";
if (item.title) {
title = item.title.text;
}
document.getElementById("ItemTitle").innerText = title;
// Display the main link.
var link = "";
if (item.links.size > 0) {
link = item.links[0].uri.absoluteUri;
}
var linkElement = document.getElementById("Link");
linkElement.innerText = link;
linkElement.href = link;
// Display the body as HTML.
var content = "(no content)";
if (item.content) {
content = item.content.text;
}
else if (item.summary) {
content = item.summary.text;
}
document.getElementById("WebView").innerHTML = window.toStaticHTML(content);
//displayCurrentItem is continued below.
如前所述, SyndicationItem 物件所代表的內容類型會依據用於發佈訂閱源的訂閱標準(RSS 或 Atom)而有所不同。 例如,Atom 訂閱源能夠提供貢獻者 清單,但 RSS 訂閱則無法。 然而,串流項目中包含但兩標準都不支援的擴充元素(例如 Dublin Core 擴充元素),可透過 SyndicationItem.ElementExtensions 屬性存取,並如以下範例程式碼所示顯示。
//displayCurrentItem continued.
string extensions = "";
foreach (Windows.Web.Syndication.SyndicationNode node in item.ElementExtensions)
{
string nodeName = node.NodeName;
string nodeNamespace = node.NodeNamespace;
string nodeValue = node.NodeValue;
extensions += nodeName + "\n" + nodeNamespace + "\n" + nodeValue + "\n";
}
this.listView.Items.Add(itemTitle + "\n" + itemLink + "\n" + itemContent + "\n" + extensions);
}
// displayCurrentItem function continued.
var bindableNodes = [];
for (var i = 0; i < item.elementExtensions.size; i++) {
var bindableNode = {
nodeName: item.elementExtensions[i].nodeName,
nodeNamespace: item.elementExtensions[i].nodeNamespace,
nodeValue: item.elementExtensions[i].nodeValue,
};
bindableNodes.push(bindableNode);
}
var dataList = new WinJS.Binding.List(bindableNodes);
var listView = document.getElementById("extensionsListView").winControl;
WinJS.UI.setOptions(listView, {
itemDataSource: dataList.dataSource
});
}