2011-01-25 10 views
3

私は有名な記事を読んだことがあります。限られた成功と失敗の両方の試みを見たことがあります。ああ、炎の戦争、ここと他の場所。RegexでXML/XHTMLデータを解析する

しかし、これを行うことができます。

実際の議論(事実を読んで)は、正規表現が構造化されたデータツリーを解析できないことに気付いていますが、状態を監視し変更することができないため、盲目的にその可能性を破棄しています。状態を保持するにはアプリケーションロジックが必要ですが、このが動作しているので、の例で示されています。

関連するスニペットは、以下:

const PARSE_MODE_NEXT = 0; 
const PARSE_MODE_ELEMENT = 1; 
const PARSE_MODE_ENTITY = 3; 
const PARSE_MODE_COMMENT = 4; 
const PARSE_MODE_CDATA = 5; 
const PARSE_MODE_PROC = 6; 

protected $_parseModes = array(
     self::PARSE_MODE_NEXT  => '% < (?: (?: (?<entity>!) (?: (?<comment>--) | (?<cdata>\[CDATA\[))) | (?<proc>\?))? %six', 
     self::PARSE_MODE_ELEMENT => '% (?<close>/)? (?<element> .*?) (?<empty> /)? > (?<text> [^<]*) %six', 
     self::PARSE_MODE_ENTITY => '% (?<entity> .*?) > (?<text> [^<]*) %six', 
     self::PARSE_MODE_COMMENT => '% (?<comment> .*?) --> (?<text> [^<]*) %six', 
     self::PARSE_MODE_CDATA => '% (?<cdata> .*?) \]\]> (?<text> [^<]*) %six', 
     self::PARSE_MODE_PROC  => '% (?<proc> .*?) \?> (?<text> [^<]*) %six', 
    ); 

public function load($string){ 
    $parseMode = self::PARSE_MODE_NEXT; 
    $parseOffset = 0; 
    $context = $this; 
    while(preg_match($this->_parseModes[$parseMode], $string, $match, PREG_OFFSET_CAPTURE, $parseOffset)){ 
     if($parseMode == self::PARSE_MODE_NEXT){ 
      switch(true){ 
       case (!($match['entity'][0] || $match['comment'][0] || $match['cdata'][0] || $match['proc'][0])): 
        $parseMode = self::PARSE_MODE_ELEMENT; 
        break; 
       case ($match['proc'][0]): 
        $parseMode = self::PARSE_MODE_PROC; 
        break; 
       case ($match['cdata'][0]): 
        $parseMode = self::PARSE_MODE_CDATA; 
        break; 
       case ($match['comment'][0]): 
        $parseMode = self::PARSE_MODE_COMMENT; 
        break; 
       case ($match['entity'][0]): 
        $parseMode = self::PARSE_MODE_ENTITY; 
        break; 
      } 
     }else{ 
      switch($parseMode){ 
       case (self::PARSE_MODE_ELEMENT): 
        switch(true){ 
         case (!($match['close'][0] || $match['empty'][0])): 
          $context = $context->addChild(new ZuqMLElement($match['element'][0])); 
          break; 
         case ($match['empty'][0]): 
          $context->addChild(new ZuqMLElement($match['element'][0])); 
          break; 
         case ($match['close'][0]): 
          $context = $context->_parent; 
          break; 
        } 
        break; 
       case (self::PARSE_MODE_ENTITY): 
        $context->addChild(new ZuqMLEntity($match['entity'][0])); 
        break; 
       case (self::PARSE_MODE_COMMENT): 
        $context->addChild(new ZuqMLComment($match['comment'][0])); 
        break; 
       case (self::PARSE_MODE_CDATA): 
        $context->addChild(new ZuqMLCharacterData($match['cdata'][0])); 
        break; 
       case (self::PARSE_MODE_PROC): 
        $context->addChild(new ZuqMLProcessingInstruction($match['proc'][0])); 
        break; 
      } 
      $parseMode = self::PARSE_MODE_NEXT; 
     } 
     if(trim($match['text'][0])){ 
      $context->addChild(new ZuqMLText($match['text'][0])); 
     } 
     $parseOffset = $match[0][1] + strlen($match[0][0]); 
    } 

} 

それは完全ですか?

解読不能ですか?確かにそうではありません。

速いですか?ベンチマークはしていませんが、それはDOMと同じくらい速いとは思いません。

それは、XPath/XQueryをサポートしていますか?明らかにそうではありません。

それは他の補助作業を検証したり実行していますか?確かにありません。

それはDOMに取って代わるだろうか?地獄の番号。

これを解析しますか?

<?xml version="1.0" encoding="utf-8"?> 
<!ENTITY name="value"> 
<root> 
    <node> 
     <node /> 
     Foo 
     <node name="value"> 
      <node>Bar</node> 
     </node> 
     <!-- Comment --> 
    </node> 
    <node> 
     <[CDATA[ Character Data ]]> 
    </node> 
</root> 

はい。はい、そうです。

私は疑問にこの文を有効にします、それが要件を満たしている与えられたコミュニティのWikiになってきて、このスレッドを歓迎だろうが。

正規表現に着目すると、整形式のマークアップに対して使用すると恐ろしく失敗する状況は誰にでも分かりますか?私は私のすべての基地をカバーしていると思う。

は、私は、しかし、私はコインの両面からいくつかの洞察力が欲しい、「鍋を攪拌」のつもりはありません。

これを書いた目的はSimpleXMLが単純すぎることであり、DOMは私のアプリケーションの1つにはあまりにも厳しいことにも注意してください。

答えて

1

正規表現に焦点を当てると、整形式のマークアップに対して使用されたときに恐ろしいことが起こることがありますか?XML適合テストスイートに対して実行された場合、どのように不正な形式のXML文書を受け入れるか?

おそらく、XMLコミュニティの文化を共有する人々の最大の反論は、最も整形式のXMLドキュメントを解析するだけでなく、ほとんどの非XMLドキュメントを解析するということです彼らはあなたが病気であるとあなたに話しません。おそらくあなたはあなたの環境でそれほど重要ではないと思うかもしれませんが、最終的に、不正な形式の文書を受け入れると、人々はあなたに不正な形式の文書を送り始めます、そしてずっと以前はHTMLと同じ混乱していますあなたは古い遺産のために古いゴミを受け入れる必要があります。

整形式XMLに対してコードがどれほどうまくいくかを判断するのに十分なPHPについてはわかりません。しかし、私は動機づけに疑問を呈します。なぜなら、まったく正しい正確で高速のXMLパーザが手元にあるときに、安く汚いXMLパーザを手で書くことを望むのはなぜでしょうか?

+0

重要な点を挙げていますが、これを書いた主な理由は、「SimpleXML」が単純すぎて必要なサポートが限られていたことです。 'DOM'はあまりにも厳しく、解決しているよりも多くの問題を引き起こしました。私は環境にやさしく、環境の制約にかかわらずプロジェクトに簡単に組み込むことができました。その目的のために、私は検証に関心がなく、構造化された文書を解析して再構築する能力にのみ関心があります。 *しかし*、スピードは問題であり、DOMよりも30倍以上遅い(テストの繰り返し回数は10万回)、失敗し、使用できなくなります。 :( – Dan

+0

あなたのご意見ありがとうございました** Michael Kay **! – Dan