2017-01-12 6 views
0

У меня есть страница с элементами, которые я пытаюсь разобрать. Я хочу, чтобы class1 и class2 представляли собой отдельный текст. Однако класс 2 существует внутри класса 1. Поэтому, если я выполняю textContent, он извлекает весь текст.Как получить текстовое содержимое, разделенное <BR> в использовании DOMDocument

Heres структуры ...

<div class='class1'> 
    Name <br/> <span class='class2'>Other Name</span> 
    </div> 

Если я сделаю это ...

$dom = new DOMDocument(); 
$dom->loadHTMLFile($url); 
$finder = new DomXPath($dom); 
$classname="class2"; 
$nodes = $finder->query("//*[contains(@class, '$classname')]"); 
foreach($nodes as $n){ 
    echo $n->textContent; 
} 

я могу получить class2 elemtn просто отлично. Но если я сделаю то же самое для класса 1. Я получаю textContent класса1, который также включает в себя содержимое класса2.

Как я могу извлечь их отдельно?

ответ

1

В вашем примере, $n содержит 5 дочерних узлов:

  1. "Имя"
  2. "< бр/>"
  3. ""
  4. "< пролет класс = 'Class2' > Другое Название </span > "
  5. " "

Свойство textContent состоит из текста этого узла и всех его потомков. Чтобы получить доступ к содержимому только первого использования ребенка:

echo $n->firstChild->textContent; 
+0

Спасибо! супер просто, теперь я чувствую себя глупо. Как мне получить четвертый элемент, так что я могу просто использовать один запрос – KyleK

+0

Что-то вроде $ node-> childNodes-> item (4) -> textContent. Что, похоже, не работает? – KyleK

+0

только что сделал $ node-> firstChild-> nextSibling-> nextSibling-> textContent. Не уверен, что это лучший способ. но он работает, поэтому Im happy – KyleK

0

В простом JavaScript, вы можете фильтровать/карту, чтобы извлечь только текст детей от узла. Что-то вроде этого:

var c1 = document.getElementsByClassName('class1')[0].childNodes; 
var allC1Text = Array.from(c1.values()) 
    .filter(v => v.nodeName === '#text') 
    .map(t => t.textContent) 
    .join('') 
    .trim(); 

var c2 = document.getElementsByClassName('class2')[0].childNodes; 
var allC2Text = Array.from(c2.values()) 
    .filter(v => v.nodeName === '#text') 
    .map(t => t.textContent) 
    .join('') 
    .trim(); 

console.log('Class1 Text:', allC1Text); 
console.log('Class2 Text:', allC2Text); 
+1

Это вопрос 'php', а не' javascript' – AlexM

0

Используя только DOMDocument, я хотел бы сделать что-то вроде этого:

<?php 
function getElementsByClassName(DOMDocument $dom, $className, $parentNode = null){ 
    $node = $parentNode ? $parentNode : $dom; 
    $a = array(); $all = $node->getElementsByTagName('*'); 
    foreach($all as $e){ 
    if($e->hasAttribute('class') && $e->getAttribute('class') === $className){ 
     $a[] = $e; 
    } 
    } 
    return $a; 
} 
function getNodeValueBeforeBr($node){ 
    return preg_replace('/\s*<\s*br\s*\/?\s*>$/i', '', $node->nodeValue); 
} 
$dom = new DOMDocument; @$dom->loadHTMLFile('yourFileName.php'); 
$class1 = getElementsByClassName($dom, 'class1'); $results = array(); 
foreach($class1 as $node){ 
    $results[] = getNodeValueBeforeBr($node); 
} 
print_r($results); 
?>