2015-11-27 1 views
1

Вопрос, аналогичный другим, заданный здесь раньше, но поскольку я не могу понять, как применять эти предложения, мне нужна помощь.XPath до следующего тега

Я хотел бы найти узлы в HTML-документ, который имеет структуру, как это (экстракты, могут различаться):

<h2>My title 1</h2> 
<h3>Sub-heading</h3> 
<p>...<span><a href='#'>...</a></span></p> 
<div>...</div> 
<h2>My title 2</h2> 
<p>No sub-heading here :O</p> 
<h3>But here</h3> 
<p>No link</p> 
<h2>And so on...</h2> 
<p>...</p> 

То, что я хотел бы выполнить, чтобы найти все узлы из один h2 до последнего элемента до следующего h2, включая сам h2. Как и в моем примере я хотел бы извлечь "блоки", подобные этим:

Блок 1:

<h2>My title 1</h2> 
<h3>Sub-heading</h3> 
<p>...<span><a href='#'>...</a></span></p> 
<div>...</div> 

Блок 2:

<h2>My title 2</h2> 
<p>No sub-heading here :O</p> 
<h3>But here</h3> 
<p>No link</p> 

Блок 3:

<h2>And so on...</h2> 
<p>...</p> 

Я не могу больше стремиться (без id, никакого текстового контента, о котором я мог бы знать, без уверенного контента и т. Д.), Кроме h2.

ответ

1

Вы можете использовать метод DOMXpath и query.

Во-первых найти все элементы h2 от тела (не вложенные элементы h2)

Затем начать foreach петли для каждого найденного h2. Затем добавьте, что h2 в массив $set, потому что вы хотите его сохранить. Затем соедините братья и сестры и добавьте их в массив $set до следующего h2, который вы найдете.

Добавить $set в $sets массив.

Например:

$html = <<<HTML 
<h2>My title 1</h2> 
<h3>Sub-heading</h3> 
<p>...<span><a href='#'>...</a></span></p> 
<div>...</div> 
<h2>My title 2</h2> 
<p>No sub-heading here :O</p> 
<h3>But here</h3> 
<p>No link</p> 
<h2>And so on...</h2> 
<p>...</p> 
<div><h2>This is nested</h2></div> 
HTML; 

$doc = new DOMDocument(); 
$doc->loadHTML($html); 
$xpath = new DOMXpath($doc); 
$domNodeList = $xpath->query('/html/body/h2'); 

$sets = array(); 

foreach($domNodeList as $element) { 
    // Save the h2 
    $set = array($element); 

    // Loop the siblings unit the next h2 
    while ($element = $element->nextSibling) { 
     if ($element->nodeName === "h2") { 
      break; 
     } 
     // if Node is a DOMElement 
     if ($element->nodeType === 1) { 
      $set[] = $element; 
     } 
    } 

    $sets[] = $set; 
} 

В $ наборы теперь содержат 3 массивов, которые будут содержать ваши добавленных DOMElements.

Demo with var_dump of $sets

+0

Удивительных - настолько очевидно, думает, я усложненный его слишком много. Большое спасибо! – chrney