# 機能設計書 6-DomCrawler

## 概要

本ドキュメントは、Symfony DomCrawlerコンポーネントの機能設計を記述する。DomCrawlerはHTMLおよびXMLドキュメントのDOM操作を容易にする機能を提供し、CSSセレクタやXPathによるノード選択が可能である。

### 本機能の処理概要

DomCrawlerコンポーネントは、HTMLまたはXMLドキュメントをDOMとして解析し、CSSセレクタやXPath式によるノード選択、フォーム要素の値取得・設定、リンクの抽出等を行う。PHPのDOMExtensionを基盤とし、より直感的なAPIを提供する。

**業務上の目的・背景**：Webアプリケーションのテストやスクレイピングでは、HTMLレスポンスから特定の要素を取得して検証する必要がある。DomCrawlerはjQueryライクなAPIでDOMの操作を簡潔に記述でき、テストの可読性を向上させる。

**機能の利用シーン**：機能テストでのHTMLレスポンス検証、Webスクレイピング、HTMLメールの内容検証、フォーム操作のテスト、HTMLドキュメントからの情報抽出等で利用される。

**主要な処理内容**：
1. HTML/XMLドキュメントのパースとDOMツリー構築
2. CSSセレクタによるノード選択（CssSelectorコンポーネント連携）
3. XPath式によるノード選択
4. フォーム要素の操作（Form, Field）
5. リンク/画像要素の抽出（Link, Image）
6. ノードのフィルタリング（first, last, eq, slice等）
7. テキスト/HTML/属性値の取得
8. 名前空間対応

**関連システム・外部連携**：CssSelector（CSS->XPath変換）、BrowserKit（レスポンスのDOM解析）、Form（フォームテスト連携）

**権限による制御**：権限制御なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|

DomCrawlerは画面機能マッピングに直接関連する画面がない。

## 機能種別

DOM操作 / HTML解析 / データ抽出

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| node | DOMNodeList/DOMNode/array/string/null | No | DOMの基点となるノードまたはHTML文字列 | - |
| uri | string | No | ベースURI（相対URL解決用） | 有効なURI |
| baseHref | string | No | base href値 | 有効なURL |

### 入力データソース

- HTMLレスポンス文字列
- XMLドキュメント文字列
- DOMNodeオブジェクト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| nodes | DOMNode[] | 選択されたDOMノードのリスト |
| text | string | ノードのテキスト内容 |
| html | string | ノードのHTML内容 |
| attr | string | ノードの属性値 |
| form | Form | フォームオブジェクト |
| link | Link | リンクオブジェクト |

### 出力先

- PHPオブジェクトとして返却

## 処理フロー

### 処理シーケンス

```
1. Crawlerインスタンス生成
   └─ HTMLまたはXML文字列、またはDOMNodeを受け取る
2. DOMドキュメント構築
   └─ HTML文字列の場合はDOMDocumentに変換
3. セレクタによるノード選択
   └─ filter(CSSセレクタ) or filterXPath(XPath式)
4. データ取得
   └─ text(), html(), attr(), each()等でデータ抽出
```

### フローチャート

```mermaid
flowchart TD
    A[HTML/XML入力] --> B[Crawler生成]
    B --> C[DOMDocument構築]
    C --> D{セレクタ種別}
    D -->|CSS| E[CssSelectorConverter::toXPath]
    D -->|XPath| F[DOMXPath::query]
    E --> F
    F --> G[ノードリスト取得]
    G --> H{操作}
    H -->|テキスト取得| I[text]
    H -->|HTML取得| J[html]
    H -->|属性取得| K[attr]
    H -->|フォーム操作| L[Form]
    H -->|リンク取得| M[Link]
    H -->|フィルタ| N[filter/eq/first/last]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | CSSセレクタのXPath変換 | CSSセレクタはCssSelectorConverterを通じてXPathに変換される | filter()メソッド使用時 |
| BR-02 | 名前空間対応 | XML文書の名前空間はregisterNamespace()で登録して使用する | XMLドキュメント操作時 |
| BR-03 | ベースURL解決 | 相対URLはbaseHrefまたはuriを基準に解決される | Link/Image取得時 |
| BR-04 | 不変性 | filter操作は新しいCrawlerインスタンスを返す（元のCrawlerは変更されない） | filter系メソッド使用時 |

### 計算ロジック

特になし。

## データベース操作仕様

DomCrawlerコンポーネントはデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | \InvalidArgumentException | 空のCrawlerノードに対する操作 | ノードの存在確認 |
| - | \LogicException | 不正なDOMノード操作 | セレクタの確認 |

### リトライ仕様

リトライ機能なし。

## トランザクション仕様

トランザクション管理なし。

## パフォーマンス要件

- DOMDocumentベースのため、巨大なHTMLドキュメントではメモリ使用量に注意
- CSSセレクタのXPath変換結果はキャッシュされる（CssSelectorConverter内部）

## セキュリティ考慮事項

- 外部HTMLの解析時はXXE（XML External Entity）攻撃に注意（HTMLパース時はデフォルトで無効）
- DomCrawlerは入力を解析するのみで、出力のサニタイズは行わない

## 備考

- PHP DOM拡張が必要
- CssSelectorコンポーネントとの連携により、CSSセレクタが利用可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Crawler.php | `src/Symfony/Component/DomCrawler/Crawler.php` | 中心クラス。DOMNodeのリストを管理し、フィルタ・取得メソッドを提供 |

**読解のコツ**: Crawlerクラスは`\Countable`と`\IteratorAggregate`を実装しており（行23）、foreach文で反復処理が可能。内部的にはDOMNode配列（`$this->nodes`、行51）を保持する。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Crawler.php | `src/Symfony/Component/DomCrawler/Crawler.php` | コンストラクタとadd()メソッド |

**主要処理フロー**:
1. **61-70行目**: コンストラクタ。node, uri, baseHrefの初期化とadd()呼び出し
2. **56行目**: isHtmlプロパティ（CSS->XPath変換時のモード判定）
3. **46行目**: DOMDocumentの保持

#### Step 3: フォーム・リンク操作を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Form.php | `src/Symfony/Component/DomCrawler/Form.php` | HTMLフォーム要素の抽象化 |
| 3-2 | Link.php | `src/Symfony/Component/DomCrawler/Link.php` | HTMLリンク要素の抽象化 |
| 3-3 | Image.php | `src/Symfony/Component/DomCrawler/Image.php` | HTML画像要素の抽象化 |
| 3-4 | Field/ | `src/Symfony/Component/DomCrawler/Field/` | フォームフィールド型群 |

### プログラム呼び出し階層図

```
Crawler(html_string, uri, baseHref)
    |
    +-- add(html_string)
    |       +-- addHtmlContent(html_string)
    |               +-- DOMDocument::loadHTML()
    |
    +-- filter(cssSelector)
    |       +-- CssSelectorConverter::toXPath(cssSelector)
    |       +-- filterXPath(xpathExpression)
    |               +-- DOMXPath::query(xpathExpression)
    |               +-- new Crawler(nodeList)
    |
    +-- text() / html() / attr(attributeName)
    |
    +-- form(values, method)
    |       +-- new Form(node, uri, method, baseHref)
    |
    +-- link()
            +-- new Link(node, uri)
```

### データフロー図

```
[入力]                        [処理]                              [出力]

HTML文字列              --->  DOMDocument::loadHTML()       --->  DOMDocument
                              |
CSSセレクタ             --->  CssSelectorConverter          --->  XPath式
                              +-- DOMXPath::query()         --->  DOMNodeList
                              |
DOMNodeList             --->  Crawler                       --->  text/html/attr/Form/Link
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Crawler.php | `src/Symfony/Component/DomCrawler/Crawler.php` | ソース | DOM操作の中心クラス |
| Form.php | `src/Symfony/Component/DomCrawler/Form.php` | ソース | フォーム要素の抽象化 |
| FormFieldRegistry.php | `src/Symfony/Component/DomCrawler/FormFieldRegistry.php` | ソース | フォームフィールドレジストリ |
| Link.php | `src/Symfony/Component/DomCrawler/Link.php` | ソース | リンク要素の抽象化 |
| Image.php | `src/Symfony/Component/DomCrawler/Image.php` | ソース | 画像要素の抽象化 |
| AbstractUriElement.php | `src/Symfony/Component/DomCrawler/AbstractUriElement.php` | ソース | URI要素の基底クラス |
| UriResolver.php | `src/Symfony/Component/DomCrawler/UriResolver.php` | ソース | 相対URI解決 |
| Field/ | `src/Symfony/Component/DomCrawler/Field/` | ソース | フォームフィールド型群 |
| Test/ | `src/Symfony/Component/DomCrawler/Test/` | ソース | テストユーティリティ |
