私は有名な記事を読んだことがあります。限られた成功と失敗の両方の試みを見たことがあります。ああ、炎の戦争、ここと他の場所。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つにはあまりにも厳しいことにも注意してください。
重要な点を挙げていますが、これを書いた主な理由は、「SimpleXML」が単純すぎて必要なサポートが限られていたことです。 'DOM'はあまりにも厳しく、解決しているよりも多くの問題を引き起こしました。私は環境にやさしく、環境の制約にかかわらずプロジェクトに簡単に組み込むことができました。その目的のために、私は検証に関心がなく、構造化された文書を解析して再構築する能力にのみ関心があります。 *しかし*、スピードは問題であり、DOMよりも30倍以上遅い(テストの繰り返し回数は10万回)、失敗し、使用できなくなります。 :( – Dan
あなたのご意見ありがとうございました** Michael Kay **! – Dan