parsing CSS classes at a node in the HTML tree

Let’s return to our topic. So, to the code above in this article, add the following:

                # Iterate over class names foreach ($class in $node.GetClasses()) { $color = "36" # Blue (color scheme slot), can be changed (" " * ($count + $indent)) + "$esc[$color`m" + $class + "$esc[0m"
        }

Тестирование

Я подготовил файл с кодом на языке HTML для тестирования своего скрипта:

<!DOCTYPE html>
<html lang="ru">
<head>
  <meta charset="utf-8" />
  <title>Тестовая страница</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
  <div class="class-name1 class-name2 class-name3">
    В одну строку, разделитель: символ пробела.
  </div>
  <div class="class-name1
				class-name2
              class-name3">
    В несколько строк (в столбик), разделители: пробелы,
    символы горизонтальной табуляции, символы новой строки.
  </div>
  <div class="    class-name1 class-name2 class-name3">
    В одну строку. Есть пробельные символы в начале.
  </div>
  <div class="class-name1 class-name2 class-name3    ">
    В одну строку. Есть пробельные символы в конце.
  </div>
</body>
</html>

В этом файле есть четыре блока div с атрибутом class. Они содержат разные варианты ввода названий классов CSS для блока. Этот файл успешно прошел проверку в известном валидаторе HTML, то есть все эти варианты валидны.

Метод GetClasses узла из библиотеки «HTML Agility Pack» во всех этих четырех вариантах выдаст одинаковый результат. То есть ненужные разделители в виде вышеупомянутых пробельных символов (пробелы, символы горизонтальной табуляции, символы новой строки) будут откинуты (будут заменены одним пробелом в местах, где требуется разделитель), а мы получим коллекцию «очищенных» названий классов CSS для перебора и анализа.

Вот как у меня выглядит вывод в консоль для вышеуказанного тестового файла:

Обработка ссылок на символы

Как известно, значение атрибута class HTML-элементов может состоять из текста (символы Юникода) с вкраплениями ссылок на символы вида &#1102; (это пример ссылки на строчную русскую букву «ю»). Ссылки на символы кроме числа (десятичный код символа в Юникоде) еще могут содержать названия символов из таблицы, приведенной в стандарте HTML.

Нужно иметь в виду, что показанный выше метод GetClasses узла из библиотеки «HTML Agility Pack» не обрабатывает ссылки на символы, встречающиеся в названиях классов. Что значит «не обрабатывает»? Это значит, что он не преобразовывает ссылки на символы в символы, которые эти ссылки на символы представляют.

А зачем преобразовывать ссылки на символы в символы? Приведу один пример. Предположим, в файле с кодом на языке HTML есть такой HTML-элемент:

<div class="имя-класса1 имя&#160;класса2">
    <!-- содержимое блока -->
</div>

Сколько тут классов CSS? На первый взгляд кажется, что к этому HTML-элементу привязано два класса CSS: имя-класса1 и имя&#160;класса2. Метод GetClasses тоже так считает и возвращает коллекцию из двух указанных имен классов.

Однако, при проверке в браузере (я использую для тестирования браузер «Microsoft Edge» на движке «Chromium» и браузер «Google Chrome») выясняется, что браузер видит здесь три класса: имя-класса1имя и класса2. Почему? Потому что ссылка на символ &#160; представляет символ пробела, а символ пробела является одним из возможных разделителей имен классов в атрибуте class HTML-элементов согласно стандарта HTML!

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

Библиотека «HTML Agility Pack» имеет в своем составе служебный класс (по-английски «utility class») HtmlAgilityPack.HtmlEntity, с помощью которого можно выполнить, в частности, конвертацию строки со ссылками на символы в строку, в которой все ссылки на символы заменены на представляемые ими символы. Это можно сделать с помощью метода DeEntitize. Данный метод работает как с числовыми ссылками на символы, так и с именованными ссылками на символы. Объект указанного класса для этого создавать не нужно.

Дополним код перебора названий классов:

        #   Перебор названий классов
        $classes = [HtmlAgilityPack.HtmlEntity]::DeEntitize($node.GetClasses()) if ($null -ne $classes) { $node.RemoveClass() $node.AddClass($classes) } foreach ($class in $node.GetClasses()) { $ color = "36" # Blue (color scheme slot), can be changed (" " * ($count + $indent)) + "$esc[$color`m"+$class+"$esc[0m"}

Before this code, we have already printed the initial value of the attribute to the console class HTML element. Now we simply remove the old value of this attribute and replace it with a value in which all character references are converted to the characters they represent. After this operation, we use the method GetClasses libraries “HTML Agility Pack” as if nothing had happened. Thus, it turns out that we have slightly improved the functionality of the library.

This is how the script looks like in my console:

Summarizing

To work with an attribute class HTML elements in the “HTML Agility Pack” library has a method GetClasses. It can be used to get the value of an attribute class one line, in which the extra separator characters are removed, and, where necessary, one separator is left in the form of a space character. Also using the method GetClasses you can get a collection of CSS class names from an attribute value class HTML element. This collection can be iterated in a loop foreach to parse individual CSS class names.

Method GetClasses does not convert character references to the characters they represent. For this conversion, you can use the method DeEntitize utility class HtmlAgilityPack.HtmlEntity.

Similar Posts

Leave a Reply Cancel reply