Как анализировать PCDATA и дочерний элемент отдельно с PHP DOM?

Я пытаюсь разобрать XML dtbook, который содержит уровни (1, 2 и 3), который позже содержит p-теги. Я делаю это с PHP DOM. Ссылка на XML

Внутри сома этих p-тегов есть noteref-теги. Я держу их в руках, но, похоже, что единственные результаты, которые я могу получить, это то, что noteref появляется перед p-тегом или после. Мне нужно, чтобы некоторые заметки появились внутри p-тега; или другими словами, где они на самом деле должны быть.

<p>Special education for the ..... <noteref class="endnote" idref="fn_5"
id="note5">5</noteref>. Interest ..... 19th century <noteref class="endnote"
idref="fn_6" id="note6">6</noteref>.</p>

Это код, который я получил для p-тега. Перед этим я перебираю dt-книгу, чтобы получить p-тег. Это отлично работает.

if($level1->tagName == "p") {
    echo "<p>".$level1->nodeValue;
    $noterefs = $level1->childNodes;
    foreach($noterefs as $noteref) {
        if($noteref->nodeType == XML_ELEMENT_NODE) {
            echo "<span><b>".$noteref->nodeValue."</b></span>";
        }
    }  
    echo "</p><br>";
}

Вот результаты, которые я получаю:

Специальное образование для..... 5. Интерес..... 19-го века 6.56

56 Специальное образование для..... 5. Интерес..... 19 век 6.

Я также хочу, чтобы p-тег не отображал содержимое тега noteref. Это должно быть сделано с помощью тега noteref (только).

Итак, кто-нибудь знает, что можно сделать, чтобы исправить эти вещи? Такое чувство, что я оба гуглил и перепробовал почти все.

1 ответ

Решение

DOMNode->nodeValue (который в PHP DOMElement такой же как DOMNode->textContent) будет содержать полный текстовый контент самого себя и всех его нисходящих узлов. Или, говоря проще: он содержит полное содержимое узла, но со всеми удаленными тегами.

Вероятно, вы захотите попробовать что-то вроде следующего (непроверенного):

if($level1->tagName == "p") {
    echo "<p>";
    // loop through all childNodes, not just noteref elements
    foreach($level1->childNodes as $childNode) {
      // you could also use if() statements here, of course
      switch($childNode->nodeType) {
        // if it's just text
        case XML_TEXT_NODE:
          echo $childNode->nodeValue;
        break;
        // if it's an element
        case XML_ELEMENT_NODE:
          echo "<span><b>".$childNode->nodeValue."</b></span>";
        break;
      }
    }  
    echo "</p><br>";
}

Имейте в виду, что это все еще довольно хрупко. Например: если какие-либо другие элементы, кроме <noteref> элементы, появляются в <p> элементы, они также будут обернуты в <span><b> элементы.

Надеюсь, я хотя бы дал вам понять, почему ваш результат <p> элементы также отображают содержимое дочерних элементов.


В качестве дополнительного примечания: если вы хотите преобразовать содержимое XML-документа в HTML или, возможно, в какую-либо другую XML-структуру, то стоит заглянуть в XSLT. Имейте в виду, что кривая обучения может быть крутой.

Другие вопросы по тегам