Как разбить строку по тегу в php при разборе html на dom tree? - PullRequest
2 голосов
/ 28 июля 2011

Вот строка:

<div>This is a test.</div>
<div>This <b>another</b> a test.</div>
<div/>
<div>This is last a test.</div>

Я хочу разделить следующую строку на массив следующим образом:

{"This is a test.", "This <b>another</b> a test.", "", "This is last a test."}

Есть идеи сделать это в php? Спасибо.

Ответы [ 2 ]

3 голосов
/ 28 июля 2011

Я предполагаю, что ваш HTML специально искажен

Есть много опций, включая xpath и многочисленные библиотеки. Regex не очень хорошая идея . Я нахожу DOMDocument быстрым и относительно простым.

getElementsByTagName, затем итерируйте их, получая innerHTML.

Пример:

<code><?php
function get_inner_html( $node ) { 
    $innerHTML= ''; 
    $children = $node->childNodes; 
    foreach ($children as $child) { 
        $innerHTML .= $child->ownerDocument->saveXML( $child ); 
    } 

    return $innerHTML; 
}
$str = <<<'EOD'
<div>This is a test.</div>
<div>This <b>another</b> a test.</div>
<div/>
<div>This is last a test.</div>
EOD;

$doc = new DOMDocument();
$doc->loadHTML($str);
$ellies = $doc->getElementsByTagName('div');
foreach ($ellies as $one_el) {
    if ($ih = get_inner_html($one_el))
        $array[] = $ih;
}
?>
<pre>
<?php print_r($array); ?>
// Выход // Обратите внимание, что там будет // четвертый элемент массива без проверки `if ($ ih = get_inner_html ($ one_el))` `: массив ( [0] => Это тест. [1] => Это еще один тест. [2] => Это последний тест. )

Попробуйте здесь


Примечание:

Вышеописанное будет работать нормально, если у вас нет вложенных DIVS. Если у вас есть вложенность, вы должны исключить вложенные дочерние элементы при циклическом просмотре innerHTML.

Например, допустим, у вас есть этот HTML:

<div>One
    <div>Two</div>
    <div>Three</div>
<div/>
<div>Four
    <div>Five</div>
</div>

Вот как с этим справиться и получить массив с порядковым номером:

Работа с вложением

<code><?php
function get_inner_html_unnested( $node, $exclude ) { 
    $innerHTML= ''; 
    $children = $node->childNodes; 
    foreach ($children as $child) {     
        if (!property_exists($child, 'tagName') || ($child->tagName != $exclude)) 
            $innerHTML .= trim($child->ownerDocument->saveXML( $child ));
    } 

    return $innerHTML; 
}
$str = <<<'EOD'
<div>One
    <div>Two</div>
    <div>Three</div>
<div/>
<div>Four
    <div>Five</div>
</div>
EOD;

$doc = new DOMDocument();
$doc->loadHTML($str);
$ellies = $doc->getElementsByTagName('div');
foreach ($ellies as $one_el) {
    if ($ih = get_inner_html_unnested($one_el, 'div'))
        $array[] = $ih;
}
?>
<pre>
<?php print_r($array); ?>

Попробуйте здесь

0 голосов
/ 28 июля 2011

Эта make_array функция должна помочь вам:

function make_array($string)
{
    $regexp = "(\s*</?div/?>\s*)+";
    $string = preg_replace("@^$regexp@is", "", $string);
    $string = preg_replace("@$regexp$@is", "", $string);
    return preg_split("@$regexp@is", $string);
}

Когда передается строка, которую вы привели в качестве примера, она выводит следующий массив:

Array
(
    [0] => "This is a test."
    [1] => "This <b>another</b> a test."
    [2] => "This is last a test."
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...