Как отрезать часть HTML внутри <div>и сохранить ее как строку HTML, используя xpath и domdocument? - PullRequest
3 голосов
/ 28 января 2012

Я хотел бы отрезать некоторую часть html, я могу взять ее, используя XPath и DomDocument, но проблема в том, что мне нужен результат в виде строки кода html.Обычно я бы использовал рег.выраж.для этого, но я не хотел бы делать сложный шаблон поиска, который бы обрабатывал начало и конец тега.

Это пример ввода:

some html code before
<div>this <b>is</b> what I want</div>
some html after

и вывод:

<div>this <b>is</b> what I want</div>

Я пытался что-то вроде этого:

 subject = 'some html code before
<div>this <b>is</b> what I want</div>
some html after';

$doc = new DOMDocument();                   
$doc->loadHTML($subject);
$xpath = new DOMXpath($doc);
$result = $xpath->query("//div/*");
echo $result->saveHTML();

, но я получил только ошибку: вызов неопределенного метода DOMNodeList :: saveHTML ()

Кто-нибудь знает, какполучить результат в виде html-строки, используя DomDocument и XPath?

Ответы [ 4 ]

2 голосов
/ 28 января 2012

Спасибо, джентльмен, за то, что указал на мое недоразумение с доступом к методам, недоступным в дочернем объекте.Но строка:

echo $doc->saveHTML($result->item(0));

генерирует только предупреждение (без html-строки, которую я хочу иметь).К счастью, я нашел другое решение, и вот оно:

<?php
$subject = '<html>
    <head>
        <title>A very short ebook</title>
        <meta name="charset" value="utf-8" />
    </head>
    <body>
        <h1 class="bookTitle">A very short ebook</h1>
        <p style="text-align:right">Written by Kovid Goyal</p>
        <div class="introduction">
            <p>A very short ebook to demonstrate the use of XPath.</p>
        </div>

        <h2 class="chapter">Chapter One</h2>
        <p>This is a truly fascinating chapter.</p>

        <h2 class="chapter">Chapter Two</h2>
        <p>A worthy continuation of a fine tradition.</p>
    </body>
</html>';


$doc = new DOMDocument();                   
$doc->loadHTML($subject);

$xpath = new DOMXpath($doc);
$result = $xpath->query("//div");

//echo $doc->saveHTML($result->item(0));

echo domNodeList_to_string($result);

function domNodeList_to_string($DomNodeList) {
    $output = '';
    $doc = new DOMDocument;
    while ( $node = $DomNodeList->item($i) ) {
        // import node
        $domNode = $doc->importNode($node, true);
        // append node
        $doc->appendChild($domNode);
        $i++;
    }
    $output = $doc->saveHTML();
    $output = print_r($output, 1);
    // I added this because xml output and ajax do not like each others
    //$output = htmlspecialchars($output);
    return $output;
}
php>

, поэтому, если у кого-то есть запрос, подобный этому:

$result = $xpath->query("//div");

, тогда получится вывод необработанной строки html:

<div class="introduction">
        <p>A very short ebook to demonstrate the use of XPath.</p>
    </div>

если запрос:

$result = $xpath->query("//p");

, тогда вывод будет:

<p style="text-align:right">Written by Kovid Goyal</p><p>A very short ebook to demonstrate the use of XPath.</p><p>This is a truly fascinating chapter.</p><p>A worthy continuation of a fine tradition.</p>

Кто-нибудь знает более простой (встроенный в php) метод для получения того же результата?

1 голос
/ 29 января 2012

Попробуйте это:

$subject = 'some html code before<div>this <b>is</b> what I want</div>some html after';
$doc = new DOMDocument('1.0');                   
$doc->loadHTML($subject);
$xpath = new DOMXpath($doc);
$result = $xpath->query("//div");
$docSave = new DOMDocument('1.0');
foreach ( $result as $node ) {
    $domNode = $docSave->importNode($node, true);
    $docSave->appendChild($domNode);
}
echo $docSave->saveHTML();
1 голос
/ 28 января 2012

В соответствии с инструкциями по php DOMXPath::query документы , функция:

Возвращает DOMNodeList, содержащий все узлы, соответствующие данному XPath выражение. Любое выражение, которое не возвращает узлы, вернет пустой DOMNodeList.

Это означает, что $result в следующем коде будет DOMNodeList документами объектом. Поэтому, если вы хотите вытащить отдельный HTML-код изнутри, вам нужно использовать методы, доступные с объектом DOMNodeList. В этом случае метод item:

$result = $xpath->query("//div");
echo $doc->saveHTML($result->item(0));

$result->item(0) возвращает первое DOMNode в DOMNodeList, созданном вашим запросом xpath.

1 голос
/ 28 января 2012

Попробуйте это:

$subject = 'some html code before
<div>this <b>is</b> what I want</div>
some html after';

$doc = new DOMDocument();                   
$doc->loadHTML($subject);
$xpath = new DOMXpath($doc);
$result = $xpath->query("//div");
echo $doc->saveHTML($result->item(0)); //echoes what you want :)

Функция saveHTML принадлежит объекту DOMDocument, вы не можете вызвать его напрямую на узле (гораздо реже для NodeList, который возвращает запрос), но то, что вы можете сделать это передать ему узел в качестве параметра.

Кроме того, ваш запрос был неверным: вам нужен элемент div (т. Е. //div), а не его дочерние элементы (//div/*).

...