Получение относительных DOM-узлов в PHP - PullRequest
2 голосов
/ 27 ноября 2010

Я хочу получить данные следующего тега элемента в документе, например:

Я хотел бы получить <blockquote> Content 1 </blockquote> только для каждого другого диапазона.

<html>
<body>


<span id=12341></span>
<blockquote>Content 1</blockquote>
<blockquote>Content 2</blockquote>

<!-- misc html in between including other spans w/ no relative blockquotes-->

<span id=12342></span>
<blockquote>Content 1</blockquote>

<!-- misc html in between including other spans w/ no relative blockquotes-->

<span id=12343></span>
<blockquote>Content 1</blockquote>
<blockquote>Content 2</blockquote>
<blockquote>Content 3</blockquote>
<blockquote>Content 4</blockquote>

<!-- misc html in between including other spans w/ no relative blockquotes-->    

<span id=12344></span>
<blockquote>Content 1</blockquote>
<blockquote>Content 2</blockquote>
<blockquote>Content 3</blockquote>


</body>
</html>

Теперь мне интересно две вещи:

1.) Как мне написать выражение, которое соответствует и выводит только кавычки, которые следуют сразу после закрытого элемента (<span></span>)?

2.) Если бы я хотел, как я мог бы получить Контент 2, Контент 3 и т. Д., Если мне когда-нибудь понадобится вывести их в будущем, при этом применяя правила предыдущего вопроса?

Ответы [ 4 ]

3 голосов
/ 27 ноября 2010

Теперь две вещи, которые меня интересуют:

1.) Как я могу написать выражение, которое соответствует и выводит только кавычки, которые следуют сразу после закрытого элемента (<span></span>)?

При условии, что предоставленный текст преобразуется в правильно сформированный XML-документ (необходимо заключить значения атрибутов id в кавычки)

Использовать :

/*/*/span/following-sibling::*[1][self::blockquote]

Это означает на английском языке: Выбрать все blockquote элементов, каждый из которых является первым, непосредственным следующий брат или сестра элемента span , являющегося потомком верхнего элемента документа .

2.) Если бы я хотел, то как могЯ получаю Контент 2, Контент 3 и т. Д., Если мне когда-нибудь понадобится вывести их в будущем, при этом применяя правила предыдущего вопроса?

Да .

Вы можете получить все наборы blockquote элементов после span:

 /*/*/span/following-sibling::blockquote
          [preceding-sibling::*[not(self::blockquote)][1][self::span]]

Вы можете получить набор blockquote элементы, следующие после (N + 1) -го span по :

/*/*/span/following-sibling::blockquote
           [preceding-sibling::*
             [not(self::blockquote)][1]
                [self::span and count(preceding-sibling::span)=$vN]
           ]

, где $vN следует заменить числом N.

Таким образом, набор смежных наборов blockquote элементов, следующих за первым span, выбирается с помощью :

/*/*/span/following-sibling::blockquote
           [preceding-sibling::*
             [not(self::blockquote)][1]
                [self::span and count(preceding-sibling::span)=0]
           ]

множеством смежных наборов blockquote элементов, следующих за вторым span выбирается с помощью :

/*/*/span/following-sibling::blockquote
           [preceding-sibling::*
             [not(self::blockquote)][1]
                [self::span and count(preceding-sibling::span)=1]
           ]

и т. Д. ....

См. В XPath Visualizer узлы, выбранные следующим выражением :

/*/*/span/following-sibling::blockquote
           [preceding-sibling::*
             [not(self::blockquote)][1]
                [self::span and count(preceding-sibling::span)=3]
           ]

alt text

0 голосов
/ 28 ноября 2010

Помимо @Dimitre good answer , вы также можете использовать:

/html
   /body
      /blockquote[preceding-sibling::*[not(self::blockquote)][1]
                     /self::span[@id='12341']]
0 голосов
/ 27 ноября 2010

Попробуйте следующее *

/html/body/span/following-sibling::*[1][self::blockquote]

для сопоставления любых первых кавычек после элемента span, которые являются прямыми дочерними элементами тела или

//span/following-sibling::*[1][self::blockquote]

для сопоставления любые первые цитаты, следующие за элементом span в любом месте документа

* edit: fixed Xpath.Кредиты Димитру.Моя первоначальная версия будет соответствовать любой первой цитате после интервала, например, она будет соответствовать блочной цитате интервала p, что не является тем, что вы хотели.

Оба из вышеперечисленных будут соответствовать "Содержимое1 "цитаты.Если вы хотите сопоставить другие кавычки после интервала (братья и сестры, а не потомки), удалите [1]

Пример:

$dom = new DOMDocument;
$dom->load('yourFile.xml');
$xp = new DOMXPath($dom);
$query = '/html/body/span/following-sibling::*[1][self::blockquote]';
foreach($xp->query($query) as $blockquote) {
    echo $dom->saveXml($blockquote), PHP_EOL;
}

Если вы хотите сделать это без XPath,Вы можете сделать

$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->load('yourFile.xml');
$body = $dom->getElementsByTagName('body')->item(0);
foreach($body->getElementsByTagName('span') as $span) {
    if($span->nextSibling !== NULL &&
       $span->nextSibling->nodeName === 'blockquote')
    {
        echo $dom->saveXml($span->nextSibling), PHP_EOL;
    }
}

Если HTML-код, который вы обрабатываете, не является допустимым XHTML, используйте loadHtmlFile () вместо этого, чтобы загрузить разметку.Вы можете подавлять ошибки с помощью libxml_use_internal_errors(TRUE) и libxml_clear_errors().

Также см. Лучшие методы для анализа HTML для альтернатив DOM (хотя я считаю DOM хорошим выбором).

0 голосов
/ 27 ноября 2010

Краткий ответ: загрузите ваш HTML в DOMDocument и выберите нужные вам узлы с помощью XPath.

http://www.php.net/DOM

Длинный ответ:

$flag = false;
$TEXT = array();
foreach ($body->childNodes as $el) {
    if ($el->nodeName === '#text') continue;
    if ($el->nodeName === 'span') {
        $flag = true;
        continue;
    }
    if ($flag && $el->nodeName === 'blockqoute') {
        $TEXT[] = $el->firstChild->nodeValue;
        $flag = false;
        continue;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...