Сложный Xpath получает все значения, исключая некоторые определенные c атрибуты класса - PullRequest
1 голос
/ 24 января 2020

У меня есть разметка HTML, как показано ниже:

<body>
    <div>......</div>
    ............
    <div class="entry-content">
        <div class="code1 code2">(ads.....);</div>
        <p><img src="https://www..."></img></p>
        <h2> title </h2>
        <div class="code1-block code2">(ads.....);</div>
        <div class="data1 dta-ta1">
              <ul><li><p> text</p></li>
                  <li><span> text2 </span></li>
                  <li><span> text3 </span></li>
                  <div class="codex1 code-block"><span>(ads ....); </span></div>
                  <li><span> text4 </span></li>
                  <div class="codex1 code-block"><span>(ads ....); </span></div>
              </ul>
        </div> 
        <div class="codex2-block code2">(ads.....);</div>
        <div class="data2-entry dta-ta2">
              <p>
                <span> text5</span>
              </p>
              <p> text6 </p>
              <p> text7 </p
              <div class="codex1 code-block"><span>(ads ....); </span></div>
              <li><span> text8 </span></li>
              <div class="codex1 code-block"><span>(ads ....); </span></div>
        </div>
  </div>
</body>

Я пытался "go в div с class="entry-content" получить весь текст из его дочерних узлов, кроме дочерних узлов с class= "code1", "code2", "codex1", "codex2"

Мой код, как показано ниже, просто переходит в div и получает все тексты из дочерних узлов. Однако я не могу удалить текст из дочерних узлов с code1 & code2. Я благодарен за вашу поддержку. Спасибо.

 $classname='entry-content';
 $a = new DOMXPath($dom);
 $query = "//*[contains(concat(' ', normalize-space(@class), ' '), ' $classname ')]";

 $list = $a->query($query);

 if ($list->length > 0) {
    foreach ($list as $element) {
        $nodes = $element->childNodes;

          foreach ($element as $node) {
             $bodytext = trim(preg_replace('/[\r\n]+/', ' ', $node->nodeValue));
             $bodyContent .= '<p>' . $bodytext . '</p>';
          }
    }
 }

Мой ожидаемый результат:

https://www ...

title

text2

text3

text4

text5

text6

text7

text8

1 Ответ

1 голос
/ 24 января 2020

Ваш входной документ неправильно сформирован, > отсутствует для </p, а один div не закрыт должным образом. С фиксированным входным документом выражение рабочего пути составляет

Выражение XPath

//div[@class='content']//text()[not(ancestor::div/@class[contains(., 'code')])][normalize-space()]

Выбирает все текстовые узлы, но только если они не имеют предка div элемент с атрибутом class, значение которого содержит «код», а также выбранные текстовые узлы не могут быть только пробелами.

Вывод

Отдельный результаты разделяются ------:

 title 
-----------------------
 text
-----------------------
 text2 
-----------------------
 text3 
-----------------------
 text4 
-----------------------
 text5
-----------------------
 text6 
-----------------------
 text7 
-----------------------
 text8 

Обновление

Я пытался с вашим ответом. Это работает, однако мне все еще нужен источник из тега img. Как мне это получить?

Можно также выбрать атрибут source элемента img, но это сделает выражение Xpath еще более сложным. Вам нужно просто добавить еще одну строку PHP, чтобы оценить отдельное выражение пути, например:

//div[@class='entry-content']/p/img/@source

Обновление 2

Хотя я абсолютно не рекомендую используйте это выражение (потому что оно запутывает ваш код), вот как можно объединить оба выражения в одно с оператором объединения:

//div[@class='entry-content']//text()[not(ancestor::div/@class[contains(., 'code')])][normalize-space()] | //div[@class='entry-content']//p/img/@src
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...