XML DOM - Обход дерева узлов

Обход означает перебор или перемещение в цикле по дереву узлов.

Обход дерева узлов

Часто возникает необходимость пройтись в цикле по всему XML-документу, например, когда нужно извлечь значение каждого элемента.

Эту операцию и называют "обход дерева узлов" XML-документа.

В следующем примере в цикле просматриваются все дочерние узлы элемента <book> и выводятся их имена и значения:


<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>
var x, i ,xmlDoc;
var txt = "";
var text = "<book>" +
"<title>Everyday Italian</title>" +
"<author>Giada De Laurentiis</author>" +
"<year>2005</year>" +
"</book>";

parser = new DOMParser();
xmlDoc = parser.parseFromString(text,"text/xml");

// documentElement всегда содержит корневой узел
x = xmlDoc.documentElement.childNodes;
for (i = 0; i < x.length; i++) {
    txt += x[i].nodeName + ": " + x[i].childNodes[0].nodeValue + "<br>";
}
document.getElementById("demo").innerHTML = txt;
</script>

</body>
</html>

Результат:


title: Everyday Italian
author: Giada De Laurentiis
year: 2005

Объяснение примера:

  1. Загружаем строку XML в переменную xmlDoc
  2. Получаем дочерние узлы корневого элемента
  3. Для каждого дочернего узла выводим имя узла и значение текстового узла.

Браузерные различия парсинга DOM

Все современные браузеры поддерживают спецификацию W3C DOM.

Однако между браузерами есть некоторые различия. И одно из важное отличие это то, как они обрабатывают пробелы и символы новой строки.

DOM – пробелы и символ новой строки

XML часто содержит символы новой строки или пробелов между узлами. Это часто случается, когда документ редактируется в простом редакторе, например в Блокноте.

Следующий пример (отредактированный в Блокноте) содержит CR/LF (символ новой строки) между каждой строкой и два пробела перед каждым дочерним узлом:


<book>
  <title>Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>

Internet Explorer 9 и более ранние версии этого браузера, в отличие от других браузеров, НЕ обрабатывают пробелы или новые строки как текстовые узлы.

В следующем примере будет выведено количество дочерних узлов у корневого элемента (из файла books.xml). IE9 и более ранние версии будут выводить 4 дочерних узла, а IE10 и более поздние версии и другие браузеры будут выводить 9 дочерних узлов:


function myFunction(xml) {
  var xmlDoc = xml.responseXML;
  x = xmlDoc.documentElement.childNodes;
  document.getElementById("demo").innerHTML =
    "Кол-во дочерних узлов: " + x.length;
}

PCDATA – Анализируемые символьные данные

Обычно парсеры XML анализируют/парсят весь текст в документе XML.

Когда XML-элемент парсится, также синтаксическому разбору подвергается и текст между XML-тегами:


<message>Этот текст также пропарсен</message>

Парсер делает это, потому что XML элементы могут содержать другие элементы, как в следующем примере, где элемент <name> содержит два других элемента (<first> и <last>):


<name><first>Bill</first><last>Gates</last></name>

и парсер разобьет такой элемент на подэлементы следующим образом:


<name>
  <first>Bill</first>
  <last>Gates</last>
</name>

Анализируемые символьные данные (PCDATA) — это термин, используемый для обозначения текстовых данных, которые будут подвергаться синтаксическому разбору парсером XML.

CDATA – (Неанализируемые) Символьные данные

Термин CDATA используется для обозначения текстовых данных, которые не должны подвергаться синтаксическому разбору парсером XML.

Такие символы, как "<" и "&" запрещено использовать в элементах XML.

Символ "<" вызовет ошибку, потому что парсер интерпретирует его как начало нового элемента.

Символ "&" вызовет ошибку, потому что парсер интерпретирует его как начало символьной сущности.

Некоторые текстовые данные, например, код JavaScript, содержат много символов "<" или "&". И чтобы избежать ошибок парсера, такие текстовые данные можно определить как CDATA.

Парсер игнорирует все, что находится внутри раздела CDATA.

Определение раздела CDATA начинается с "<! [CDATA [" и заканчивается "]]>":


<script>
<![CDATA[
function matchwo(a,b) {
    if (a < b && a < 0) {
        return 1;
    } else {
        return 0;
    }
}
]]>
</script>

В приведенном выше примере все, что находится в разделе CDATA будет проигнорировано парсером.

Примечания к разделам CDATA:

  • Раздел CDATA не может содержать строку "]]>". Вложенные разделы CDATA не допускаются.
  • Строка "]]>", обозначающая конец раздела CDATA, не может содержать пробелов или разрывов строк.