Я прочитал знаменитый пост. Я видел попытки как с ограниченным успехом, так и безуспешно. О, пламенные войны, как здесь, так и в других местах.
Но это можно сделать.
Хотя мне известно, что фактический аргумент (факт чтения) заключается в том, что регулярные выражения не способны анализировать деревья структурированных данных из-за их неспособности отслеживать и изменять состояние, я чувствую, что некоторые слепо отказываются от этой возможности. Логика приложения необходима для сохранения состояния, но, как показывает этот пример working , это можно сделать.
Ниже приведен соответствующий фрагмент:
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>
Да. Да, это будет.
Хотелось бы, чтобы этот поток стал вики-сообществом, если он соответствует требованиям, но я превращу это утверждение в вопрос.
Сосредоточив внимание на регулярном выражении, может ли кто-нибудь предвидеть ситуацию, при которой это ужасно потерпит неудачу при использовании против правильно сформированной разметки? Я думаю, что покрыл все свои базы.
У меня нет намерения "размешивать горшок", однако я хотел бы получить некоторое представление с обеих сторон медали.
Обратите внимание, что цель написания этого состояла в том, что SimpleXML
было слишком простым, а DOM
было слишком строгим для одного из моих приложений.