Мир, соответствующий DOM, полностью отличается от SAX. Основа сущности DOM'а - это вывод из процесса синтаксического разбора. При использовании SAX наша программа реагировала на специфичные точки в процессе разбора, при использовании DOM данные не могут использоваться до тех пор, пока не будет разобран весь документ. Вывод из синтаксического анализатора DOM предназначен для использования с интерфейсом DOM, определенном в объекте org.w3c.dom.Document. К этому объекту документа применим формат дерева, которое строится на интерфейсе DOM org.w3c.dom.Node. Наследуя от этого интерфейса, DOM предоставляет несколько специфичных для XML интерфейсов - Element, Document, Attr и Text. Ваше приложение, ориентированное на DOM, теперь может перемещать и манипулировать различными аспектами дерева.
Прежде, чем вдаваться в подробности, вы должны немного узнать об эволюции DOM'а. Первая версия DOM'а не имела официальной спецификации, была только объектная модель, которую реализовывали Navigator 3 и Explorer 3 в своих браузерах. Конечно же, эти объектные модели не были полностью законченными, так что я считаю, что в этом случае применим термин DOM Level 0.
DOM Level 1 является попыткой получить совместимость некоторого уровня между браузерами. Необходимо было быстро создать Level 1, прежде чем разные стороны пойдут по противоположным направлениям. Получив такие ограничения, DOM Level 1 был на удивление хорошей спецификацией и охватывал большинство нужд программистов для обработки XML.
DOM Level 2 произвел чистку интерфейсов DOM Level 1. Была добавлена поддержка пространства имен в интерфейсы Element и Attr, и было добавлено некоторое количество поддерживаемых интерфейсов для событий, пересечений, границ, представления и страниц стилей. В настоящее время (2002), все главные синтаксические анализаторы XML поддерживают DOM Level 2 и это должно быть вашим стандартом кодирования.
Скоро выйдет DOM Level 3. Xerces 2 начал поддерживать частично DOM Level 3. DOM 3 будет предоставлять независимые от синтаксического анализатора методы для создания нового объекта Document либо посредством синтаксического разбора файла, либо путем построения черновой формы в памяти. DOM 3 добавит поддержку DTD и Схем. Таким образом, DOM 3 добавит новую функциональность, а ваш код DOM 2 должен продолжать работать.
Вот пример NodeWalker.java, который использует DOM:
import
org.apache.xerces.parsers.DOMParser;
import
org.w3c.dom.*;
public class
NodeWalker
{
static
String outStr
[]
=
new
String
[
250
]
;
static
int
lineNum =
0
;
static public
void
main
(
String
[]
argv
) {
try
{
// Xerces Parser
DOMParser parser =
new
DOMParser
()
;
parser.parse
(
argv
[
0
])
;
Document doc = parser.getDocument
()
;
walker
(
doc.getDocumentElement
())
;
}
catch
(
Exception e
) {
e.printStackTrace
(
System.err
)
;
}
// output
System.out.println
(
"Num of line:"
+ lineNum
)
;
for
(
int
i =
0
; i < lineNum; i++
) {
System.out.println
(
outStr
[
i
])
;
}
}
public static
void
walker
(
Node node
) {
if
(
node ==
null
) {
return
;
}
int
type = node.getNodeType
()
;
switch
(
type
) {
case
Node.ELEMENT_NODE:
{
// Name of this node
outStr
[
lineNum
]
= node.getNodeName
()
;
lineNum++;
// attributes of this node
int
length =
(
node.getAttributes
()
!=
null
)
? node.getAttributes
()
.getLength
()
:
0
;
for
(
int
i =
0
; i < length; i++
) {
Attr attrib =
(
Attr
)
node.getAttributes
()
.item
(
i
)
;
outStr
[
lineNum
]
= attrib.getNodeName
()
;
lineNum++;
}
// children of this node
NodeList children = node.getChildNodes
()
;
if
(
children !=
null
) {
length = children.getLength
()
;
for
(
int
i =
0
; i < length; i++
) {
walker
(
children.item
(
i
))
;
}
}
break
;
}
case
Node.TEXT_NODE:
{
String str = node.getNodeValue
()
.trim
()
;
if
(
str.indexOf
(
"n"
)
<
0
&& str.length
()
>
0
) {
outStr
[
lineNum
]
= str;
lineNum++;
}
break
;
}
}
}
}
Обратите внимание, что метод parse( ) возвращает void. Эти изменения позволяют приложению использовать класс синтаксического анализатора DOM и класс синтаксического анализатора SAX поочередно. Однако для этого требуются дополнительные методы для получения результирующего объекта Document после XML разбора. В случае Apache Xerces такой метод называется getDocument( ).
Метод разбора транслирует поток символов из XML файла в поток признаков. Эти признаки строятся во временную структуру в памяти, программа может переносить ее и манипулировать ей. DOM является API для XML документа. Оно предполагается как объектно-ориентированное представление XML документа, в отличие от абстрактного представления типов данных. Это значит, что каждый компонент документа определен в виде интерфейса, указывающего его поведение. Данные могут быть доступны только через интерфейс. DOM определяет интерфейс Node, а интерфейсы подклассов Element, Attribute и CharacterData наследуются от Node. NodeWalker просто переключает Node.ELEMENT_NODE и Node.TEXT_NODE, мы можем добавить другие узлы, включая CDATA_SECTION и PROCESSING_INSTRUCTION_NODE. Интерфейс Node определяет методы для доступа к компонентам узла. Например, parentNode( ) возвращает родительский узел; childNodes( ) возвращает множество детей. Кроме того, существуют методы для изменения узлов и для создания новых узлов. Поэтому приложение может полностью реструктуризировать документ с помощью DOM.
Интерфейс Document базируется на интерфейсе Node, который поддерживает объект W3C Node. Узлы представляют единичные узлы дерева документа и все, что встречается - текст, комментарии и теги - трактуются как узлы. Интерфейс узла имеет все методы, которые вы можете использовать для работы с узлами и для перемещения по DOM'у. Давайте взглянем на следующий код из примера:
for
(
Node node =
doc.getDocumentElement
()
.getFirstChild
()
;
node !=
null
;
node = node.getNextSibling
()) {
Этот цикл for начинает свою работу с использования метода интерфейса документа getDocumentElement( ) для получения корневого узла документа. Метод getFirstChild( ) интерфейса узла возвращает узел первого дочернего элемента для корня. До тех пор, пока не будет получено значение null, цикл for продолжит движение. Узлы инкрементируются посредством метода getNextSibling( ), который возвращает узел, следующий за вызываемым.
← | SAX | Плюсы и минусы SAX и DOM | → |