# 使い方
## 3つのパーサ
対応する形式ごとにモジュールが分かれており,いずれも同じ入口を公開しています.
```rust
pub fn parse(text: &str) -> ParseResult<Vec<Feed>>
```
| `feed_parser::parsers::rss1` | RSS 1.0 (RDF) | `<item>` |
| `feed_parser::parsers::rss2` | RSS 2.0 | `<item>` |
| `feed_parser::parsers::atom` | Atom | `<entry>` |
`parse` は文書全体を受け取り,エントリ要素ごとに `Feed` を1つずつ,文書中の順序で返します.
チャンネルレベルのメタデータは返りません.結果が表すのはエントリです.
```rust
use feed_parser::parsers::{Feed, atom};
let feeds: Vec<Feed> = atom::parse(atom_document)?;
for feed in &feeds {
println!("{} — {}", feed.title, feed.link);
}
# Ok::<(), feed_parser::parsers::errors::ParseError>(())
```
形式の自動判定は行いません.配信元に合ったモジュールを選ぶか,順に試して最初に成功したものを
採用してください.
## `Feed` 型
```rust
pub struct Feed {
pub title: String,
pub link: String,
pub description: Option<String>,
pub summary: Option<String>,
pub updated: Option<String>,
pub publish_date: Option<String>,
pub creator: Option<String>,
pub date: Option<String>,
pub other: Option<String>,
}
```
`title` と `link` は必須です.どちらかを欠くエントリは `Feed` にできず,パーサは
[`ParseError::MissingField`](errors.ja.md) を返します.それ以外は任意で,配信元が省略した
場合は `None` になります.
日付はフィードが配信した文字列のまま保持します.RSS 2.0 の RFC 822,Atom の ISO 8601,
そのどちらにも従わない配信元と,形式は統一されていないため,このクレートは特定の解釈を
押し付けません.実際のタイムスタンプが必要な場合は,呼び出し側で `chrono` や `time` を
使って解析してください.
## 各形式と `Feed` の対応
パーサは形式ごとの要素名を上記のフィールド名へ書き換えるため,配信元によらず同じ `Feed` が
得られます.
| `<title>` | `title` | 全形式 |
| `<link>` | `link` | RSS 1.0, RSS 2.0 |
| `<link rel="alternate" type="text/html" href="...">` | `link` | Atom |
| `<description>` | `description` | 全形式 |
| `<summary>` | `summary` | 全形式 |
| `<updated>` | `updated` | 全形式 |
| `<pubDate>` | `publish_date` | RSS 1.0, RSS 2.0, Atom |
| `<published>` | `publish_date` | Atom |
| `<dc:creator>` | `creator` | 全形式 |
| `<dc:date>` | `date` | 全形式 |
Atom は1つのエントリに複数の `<link>` を持つため,パーサはエントリ自体を指すもの,すなわち
`rel="alternate"` かつ `type="text/html"` のものを選びます.異なる関係やメディアタイプを
宣言したリンク(エンクロージャ,自己参照,別表現)は読み飛ばします.
## テキスト要素に埋め込まれた未エスケープの HTML
フィードは `<title>`,`<description>`,`<summary>`,`<content>` に生の HTML を
エスケープせず埋め込むことが多く,その結果 XML として不正な文書になります.各パーサは
読み込みの前にこれらの要素の内容をエスケープし,マークアップがテキストとして残るようにします.
```rust
use feed_parser::parsers::rss2;
let rss_data = r#"
<rss version="2.0">
<channel>
<item>
<title>Rust 1.85 <b>released</b></title>
<link>http://www.example.com/item1.html</link>
</item>
</channel>
</rss>
"#;
let feeds = rss2::parse(rss_data).unwrap();
assert_eq!(feeds[0].title, "Rust 1.85 <b>released</b>");
```
`CDATA` セクションの内容は前後の空白も含めてそのまま保持され,要素まわりのインデントは
取り除かれます.Atom ではさらにテキストノードの HTML 実体参照をデコードします.Atom の
配信元は内容を二重エスケープしていることが多いためです.
このエスケープは同一行の範囲で一致します.これらの要素の中で開始タグと終了タグが別の行に
またがるマークアップはそのまま残り,実際のマークアップとしてリーダに渡るため,文字列では
なく [`ParseError::DeserializeError`](errors.ja.md) になります.同じ1行という制約は
`CDATA` にも当てはまり,他のテキストと同じ行に書かれたセクションは `<![CDATA[` と `]]>`
のマーカーごとエスケープされて値に含まれます.