Как HTML-парсеры обрабатывают текст вне элементов (текстовых узлов) - PullRequest
0 голосов
/ 05 сентября 2018

Ref этот вопрос:

Добавление HTML-тега в строку в PHP

Спрашивающий спрашивает, как правильно определить нетегированный текст в файле HTML (он хотел вставить теги по мере необходимости). Он привел этот пример:

<h2><b>Hello World</b></h2>
<p>First</p>
Second
<p>Third</p>

(Конечно, для решения конкретной поставленной проблемы требуется какой-то текст найти / заменить - достаточно сложный, чтобы удовлетворить ожидаемые варианты использования. Сам задающий вопрос действовал таким образом).

Мой вопрос такой:

  1. Что говорит новейший стандарт HTML5 о немаркированном тексте и как с ним обращаться?

  2. Как современные парсеры HTML обрабатывают нетегированный текст.

  3. Может ли рассматриваемая проблема в SO52159323 быть решена с использованием класса HTMLParser (на любом языке). Я имею в виду, пропуская текст за парсером и ожидая, что он определит нетегированный текст и его местоположение? Я попробовал это и потерпел неудачу!

PS Я знаю, что браузеры и редакторы, поддерживающие HTML, просто отображают нетегированный текст, и, по крайней мере, в случае Chrome, наблюдая с помощью инструментов dev, он не пытается создать какой-либо элемент по умолчанию - немаркированный текст просто сидит там. как мертвая утка!

1 Ответ

0 голосов
/ 06 сентября 2018

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

Что говорит новейший стандарт HTML5 о немаркированном тексте и как он нужно лечить?

Текст без тегов вводится в DoM как текстовый узел. Текстовый узел вставляется как дочерний узел элемента, в котором он появляется. Например, в этом фрагменте:

<body>
    <h2><b>Hello World</b></h2>
    <p>First</p>
    Second
    <p>Third</p>
</body>

... «Второй» - это часть текстового узла (nodeType = 3), который является дочерним узлом элемента body.

Фактически существует 4 дочерних текстовых узла (значения узлов каждого показаны в списке ниже).

  1. "CR-LF " после открытия body tag.
  2. "CR-LF " после элемента <h2><b>Hello World</b></h2>
  3. "CR-LF Second-CR-LF " после элемента <p>First</p>
  4. "CR-LF " после элемента <p>Third</p>

Вероятно, большинство "uglifiers" удалит CR_LF и пробелы из текстового узла, что в большинстве случаев может удалить их вообще.

Как современные парсеры HTML обрабатывают нетегированный текст?

Как указано выше, но по крайней мере с этими классификаторами:

  1. текст без тегов (будь то форматирование, алфавитно-цифровой или оба) между тегами <html>, но вне тегов <body>, будет перемещен внутри элемента <body>.
  2. Если теги <body> отсутствуют, парсер их вставит.

Например, используя PHPDocument (встроенный синтаксический анализатор PHP) этот вход ..

<html>
    text before body
<body>
    <h2><b>Hello World</b></h2>
    <p>First</p>
    Second
    <p>Third</p>
    fourth
    <p>Third</p>
    <!-- comment -->
</body>
    text after body
</html> 

.. создал этот DoM (нетегированный текст перемещен в элемент <body>).

<html><body>
<p>
    text before body
</p>
    <h2><b>Hello World</b></h2>
    <p>First</p>
    Second
    <p>Third</p>
    fourth
    <p>Third</p>
    <!-- comment -->

    text after body
</body></html>

и этот вход ..

<html>
    <h2><b>Hello World</b></h2>
    <p>First</p>
    Second
    <p>Third</p>
    fourth
    <p>Third</p>
    <!-- comment -->
</html>

.. создал этот DoM (<body> теги, вставленные парсером)

    <html>
    <body>
<h2><b>Hello World</b></h2>
    <p>First</p>
    Second
    <p>Third</p>
    fourth
    <p>Third</p>
    <!-- comment -->
</body>
</html>

Может ли рассматриваемая проблема в SO52159323 быть решена с помощью Класс HTMLParser (на любом языке). Я имею в виду, запустив текст мимо парсера и ожидая, что парсер идентифицирует нетегированный текст а его местонахождение?

Да. Смотрите фрагмент кода в моем ответе по адресу Добавление HTML-тега в строку в PHP . Конечно, синтаксический анализатор создает DoM, позволяющий найти узел-кандидат и выполнить необходимую обработку.

...