たとえば、DOM extensionを使用します。そのDOMXPath
クラスは、この種のタスクに特に役立ちます。
簡単にこのようなXPath式と記載されている条件を設定することができる:
//table[@class="space"]//tr[count(td) = 2]/td
から//table[@class="space"]
が"space"
ストリングに等しいclass
属性値を有する文書から全てtable
要素を選択します。 - //tr[count(td) = 2]
は、正確に2つのtd
子要素を持つすべてのtr
要素を選択します。 - /td
は、td
要素を表します。
実装例:
$html = <<<'HTML'
<table class="space">
<thead></thead>
<tbody>
<tr>
<td class="marsia">1</td>
<td class="mars">
<div>Mars</div>
</td>
</tr>
<tr>
<td class="earthia">2</td>
<td class="earth">
<div>Earth</div>
</td>
</tr>
<tr>
<td class="earthia">3</td>
</tr>
</tbody>
</table>
HTML;
$doc = new DOMDocument;
$doc->loadHTML($html);
$xpath = new DOMXPath($doc);
$cells = $xpath->query('//table[@class="space"]//tr[count(td) = 2]/td');
$i = 0;
foreach ($cells as $td) {
if (++$i % 2) {
$number = $td->nodeValue;
} else {
$planet = trim($td->textContent);
printf("%d: %s\n", $number, $planet);
}
}
出力
1: Mars
2: Earth
上記コードはそれとして、サンプルなく実用の指示と考えることになっています非常にスケーラブルではありません。論理は、XPath式が各行に対して正確に2つのセルを選択するという事実に拘束されます。実際には、例えば、行を選択したい、それらを反復処理し、ループの中に余分な条件を出してもよい:
$rows = $xpath->query('//table[@class="space"]//tr');
foreach ($rows as $tr) {
$cells = $xpath->query('.//td', $tr);
if ($cells->length < 2) {
continue;
}
$number = $cells[0]->nodeValue;
$planet = trim($cells[1]->textContent);
printf("%d: %s\n", $number, $planet);
}
DOMXPath::query()
をチェックし、その後、現在の行に対するXPath式($tr
)と呼ばれています返されたDOMNodeList
に少なくとも2つのセルが含まれている場合残りのコードは簡単です。
SimpleXML
拡張機能も使用できます。これはXPathもサポートしています。しかし、拡張子はDOM
の拡張機能に比べてずっと柔軟性がありません。
巨大なドキュメントの場合は、XMLReader
などのSAXベースのパーサーに基づく拡張を使用してください。
[DOMDocument](http://php.net/manual/en/class.domdocument.php)を使用してHTMLを解析します。 – Barmar