PHPでHTML文書を解析する

つい先日、すでに書かれたHTML文書から情報を引っ張ってっこなくちゃいけない事案が発生してしまいましたので、その方法をメモしておきます。

simplexml_load_string でオブジェクト化してみる

XMLで書かれた情報をパースしてオブジェクト化してくれる simplexml_load_string という関数があります。
これだけで解決できれば楽なのですが、今回扱うのはあくまでHTMLなので、これだけではまだ解析はできません。
試しにHTML文書を simplexml_load_string に通してみます。

$html = <<<EOF
<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 <p>html文書</p>
</body>
</html>
EOF;

$xmlObj = simplexml_load_string($html);

var_dump($xmlObj); // 結果 : bool(false)

はい、エラーが返ってきました。
HTMLはXMLと違って閉じタグがなくても良かったり、いろいろルールが違うのでこれだけではダメみたいです。

HTMLをXMLとして整形してくれるが関数が用意されていた!

実はHTMLをXMLとして整形してくれるが関数がすでに用意されていたようです。
> DOMDocument::loadHTML

$doc = new DOMDocument();
$doc->loadHTML($html);
$xml = $doc->saveXML();

リファレンスによると、こんな感じで書くみたいです。
new DOMDocumentでインスタンスを生成して、loadHTML関数でhtmlをパースして、それをsavaXML関数でxml形式に整形、という感じでしょうか。
これで無事整形されたので、あとは最初に試した通り simplexml_load_string に通してあげれば、好きなように情報を解析することができます。

$xmlObj = simplexml_load_string($xml);
var_dump($xmlObj);

結果 :

object(SimpleXMLElement)#2 (3) {
  ["@attributes"]=>
  array(1) {
    ["lang"]=>
    string(2) "ja"
  }
  ["head"]=>
  object(SimpleXMLElement)#3 (2) {
    ["meta"]=>
    object(SimpleXMLElement)#5 (1) {
      ["@attributes"]=>
      array(1) {
        ["charset"]=>
        string(5) "UTF-8"
      }
    }
    ["title"]=>
    string(8) "Document"
  }
  ["body"]=>
  object(SimpleXMLElement)#4 (1) {
    ["p"]=>
    string(10) "html文書"
  }
}

ちなみに余談ですが、
simplexml_load_string を使う時、imgタグやspanタグなどをテキストと同じ階層で使用する場合は注意が必要です。
文章で説明するより、以下のコードを見てもらうと早いと思います。

<p><img src="#" alt="画像" />サンプルテキスト</p>
<p><span style="color:red;">赤いテキスト</span>サンプルテキスト</p>
<p><!--コメントアウト-->サンプルテキスト</p>

上記のhtmlは、全て「サンプルテキスト」の部分がうまく解析されません。
xmlの閉じタグが必須という仕様が起因しているのか、上記の例の「サンプルテキスト」は全て何のタグにも囲まれていない要素と扱われて無視されてしまっているようです。
この辺りの事情に詳しい方がいましたら、どなたか教えてください…(切実

スポンサーリンク