Удаление встроенных элементов при импорте HTML в DOMDocument или SimpleXML? - PullRequest
1 голос
/ 17 января 2010

У меня есть внешний источник HTML, который я хочу очистить и преобразовать в локальный файл XML или добавить в базу данных MySQL.

Внешний источник в основном нормализован и (в некоторой степени) семантический, поэтому все, что мне нужно сделать, это использовать XPATH для получения всего td контента или всего li контента и т. Д. Проблема в том, что иногда эти элементы используйте <strong> или <b> или <i> теги для оформления нужных мне элементов.

Это технически семантически, поскольку смысл состоит в том, чтобы добавить акцент к конкретному тексту, и разработчик может захотеть использовать CSS, который не является браузером по умолчанию.

Проблема в том, что фактический контент, который я пытаюсь получить, считается дочерним по отношению к этому встроенному элементу, поэтому расширения PHP, такие как simplexml или DOMDocument и DOMNode, обрабатывают их как таковые. Например:

<table>
<tr><td>Thing 1</td><td>Thing 2</td></tr>
<tr><td>Thing 3</td><td>Thing 4</td></tr>
<tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
</table>

Результатом будет:

 [table] =>
    [tr] =>
        [td] => Thing 1
        [td] => Thing 2
    [tr] =>
        [td] => Thing 3
        [td] => Thing 4
    [tr] =>
        [td] => 
            [strong] => Thing 5
        [td] => 
            [strong] => Thing 6

Очевидно, что вышеприведенное не совсем то, что возвращает simplexml, но вышеизложенное отражает общую проблему.

Таким образом, есть ли способ, используя либо параметр, уже встроенный в DOMDocument, либо используя сложный запрос XPath, чтобы получить содержимое элемента td, в котором любые дочерние элементы (если они есть) лишены статуса потомка и всех остальных содержимое рассматривается как текст запрашиваемого элемента?

Сейчас единственное решение, которое у меня есть, это либо:

a) имеет цикл foreach, который проверяет каждый результат, например:

$result_text = ($result -> strong) ? $result - strong : $result;

b) использование регулярного выражения для удаления любых тегов <strong> из строки HTML перед импортом в любые предварительно созданные классы, такие как simplexml или DOMDocument.

Ответы [ 3 ]

1 голос
/ 17 января 2010

Разве вы не можете просто использовать strip_tags () для удаления дополнительной разметки?

$table = simplexml_load_string(
    '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>'
);

foreach ($table->xpath('//td') as $td)
{
    $content = strip_tags($td->asXML());
    echo $content, "\n";
}
1 голос
/ 17 января 2010

Пожалуйста, прочитайте первый ответ на this , прежде чем анализировать html с помощью регулярного выражения, хотя бы ради развлечения. XPath - это ответ, получите текст td вместо того, чтобы продолжать его анализировать. Так что вы просто ищете что-то вроде //td и полностью принимаете результаты этого (вместо того, чтобы продолжать строить дерево, чтобы у вас были листья, которые говорят, что они сильные или что-то в этом роде.

0 голосов
/ 17 января 2010

Если вы используете DOMDocument, после того, как вы выбрали DOMNode, свойство textContent должно содержать только текстовую его часть и все, что она есть ... точно то, что вы просили.

$table = '<table>
        <tr><td>Thing 1</td><td>Thing 2</td></tr>
        <tr><td>Thing 3</td><td>Thing 4</td></tr>
        <tr><td><strong>Thing 5</strong></td><td><strong>Thing 6</strong></td></tr>
    </table>';

$dom = new DOMDocument;
$dom->loadHTML($table);
$xpath = new DOMXPath($dom);

$els = $xpath->query('//td');
echo $els->item(4)->textContent; //Thing 5

В качестве альтернативы, в зависимости от типа узла, вы также можете проверить nodeValue. Я не могу вспомнить точно разницу, но textContent - это то, что вы хотите.

...