Проход По Узлам

Рубрика: DOM - Объектная Модель Документа

Здравствуйте, уважаемые читатели блога okITgo.ru! Сразу сделаю несколько пояснений относительно используемой в данной статье терминологии.


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


Проход по узлам осуществляется посредством взаимоотношений между узлами (таких как отец, сын, следующий брат, предыдущий брат и т.п.).


Обход Дерева Узлов

Довольно часто позникает задача циклического обхода по всем узлам XML документа, например: когда Вы хотите извлечь значение каждого элемента.

Это действие называется "Обходом дерева узлов"

Пример ниже переберает в цикле все дочерние узлы <book> и отображает их имена и значения:

Пример

<html>
<head>
<script type="text/javascript" src="loadxmlstring.js"></script>
</head>
<body>
<script type="text/javascript">
text="<book>";
text=text+"<title>Самогон и другие спиртные напитки домашнего приготовления</title>";
text=text+"<author>Байдакова Ирина</author>";
text=text+"<year>2005</year>";
text=text+"</book>";

xmlDoc=loadXMLString(text);

// documentElement всегда представляет корневой узел
x=xmlDoc.documentElement.childNodes;
for (i=0;i<x.length;i++)
{
document.write(x[i].nodeName);
document.write(": ");
document.write(x[i].childNodes[0].nodeValue);
document.write("");
}
</script>
</body>
</html>

Вывод:

title: Самогон и другие спиртные напитки домашнего приготовления
author: Байдакова Ирина
year: 2005

Попробуйте сами »

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

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

Различия в Браузерах при Разборе (Парсинге) XML Документа DOM Парсером

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

Однако, есть несколько различий между браузерами. Одно из наиболее важных отличий – это:

  • Способ обработки пробельных символов и новых строк

DOM – Пробельные Символы и Новые Строки

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

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

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

Internet Explorer НЕ будет трактовать пустые пробельные символы или переходы на новую строку как текстовые узлы, тогда как остальные браузеры БУДУТ.

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

Пример

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.documentElement.childNodes;
document.write("Количество дочерних узлов: " + x.length);

Попробуйте сами »

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

  1. Загружаем "books.xml" в xmlDoc, используя loadXMLDoc()
  2. Получаем количество дочерних узлов корневого элемента
  3. Выводим количество дочерних узлов. Результат будет разным в зависимости от того, какой браузер Вы используете. IE покажет 4 дочерних узла, тогда как остальные браузеры покажут 9.

Проход по Узлам DOM

Доступ к узлам дерева посредством взаимоотношений между узлами часто называют "проходом по узлам" или "навигацией между узлами".

В XML DOM взаимоотношения между узлами определяются как свойства узлов:

  • parentNode
  • childNodes
  • firstChild
  • lastChild
  • nextSibling
  • previousSibling

Следующее изображение иллюстрирует дерево узлов и отношения между узлами в books.xml:

Дерево Узлов

DOM – Родительский Узел (Отец)

Все узлы имеют в точности один родительский узел. Следующий код осуществляет проход к родительскому узлу <book>:

Пример

xmlDoc=loadXMLDoc("books.xml");

x=xmlDoc.getElementsByTagName("book")[0];
document.write(x.parentNode.nodeName);

Попробуйте сами »

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

  1. Загружаем "books.xml" в xmlDoc с помощью loadXMLDoc()
  2. Получаем первый элемент <book>
  3. Выводим имя родительского узла "x"

Избегайте Пустые Текстовые Узлы

Firefox и некоторые другие браузеры будут трактовать пробельные символы и переходы на новую строку как текстовые узлы, а Internet Explorer – НЕТ.

Это вызывает проблемы при использовании свойств: firstChild, lastChild, nextSibling, previousSibling.

Чтобы избежать проход к пустым текстовым узлам (пробелы и символы перехода на новую строку между узлами элементов), предлагаю использовать функцию, которая проверяет тип узла:

function get_nextSibling(n)
{
y=n.nextSibling;
while (y.nodeType!=1)
 {
 y=y.nextSibling;
 }
return y;
}

Функция выше позволит Вам использовать get_nextSibling(узел) вместо свойства узел.nextSibling.

объяснение кода:

Узлы элементов имеют тип 1. Если сестринский узел не является узлом элемента, эта функция проходит к следующим узлам, пока узел элемента не будет найден. Таким образом, результат будет одинаковый как в Internet Explorer. так и в Firefox.


Получение Первого Дочернего Элемента

Следующий код отображает первый дочерний узел элемента для первого узла <book>:

Пример

<html>
<head>
<script type="text/javascript" src="loadxmldoc.js">
</script>
<script type="text/javascript">
//проверить, является ли первый узел узлом элемента
function get_firstChild(n)
{
y=n.firstChild;
while (y.nodeType!=1)
  {
  y=y.nextSibling;
  }
return y;
}
</script>
</head>

<body>
<script type="text/javascript">
xmlDoc=loadXMLDoc("books.xml");

x=get_firstChild(xmlDoc.getElementsByTagName("book")[0]);
document.write(x.nodeName);
</script>
</body>
</html>

Вывод:

title

Попробуйте сами »

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

  1. Загружаем "books.xml" в xmlDoc посредством loadXMLDoc()
  2. Используем функцию get_firstChild на первом узле элемента <book>, чтобы плучить первый дочерний узел, который является узлом элемента
  3. Выводим имя узла первого дочернего узла, который является узлом элемента (имеет тип 1)

Спасибо за внимание! Ниже пирведены дополнительные примеры прохода по узлам XML документа, демонстрирующие использование остальных методом прохода по узлам с помощью “родственных” отношений между ними. До новых встреч на страницах сайта okITgo.ru.


Еще Примеры

lastChild()
Этот пример использует метод lastChild() и пользовательскую функцию, чтобы получить последний дочерний узел родительского узла

nextSibling()
Данный пример использует метод nextSibling() и пользовательскую функцию для получения следующего брата узла

previousSibling()
Еще пример, использующий метод previousSibling() и пользовательскую функцию для возврата предыдущего брата узла