Вопрос-ответ

Normalization in DOM parsing with java - how does it work?

Нормализация при синтаксическом анализе DOM с помощью java - как это работает?

Я видел строку ниже в коде для синтаксического анализа DOM в этом руководстве.

doc.getDocumentElement().normalize();

Зачем мы делаем эту нормализацию?

Я прочитал документы, но не смог понять ни слова.


Помещает все текстовые узлы во всю глубину поддерева под этим узлом


Хорошо, тогда может кто-нибудь показать мне (желательно с картинкой), как выглядит это дерево ?

Кто-нибудь может объяснить мне, зачем нужна нормализация?
Что произойдет, если мы не будем нормализовывать?

Переведено автоматически
Ответ 1

Остальная часть предложения:


где текстовые узлы разделены только структурой (например, элементами, комментариями, инструкциями по обработке, разделами CDATA и ссылками на сущности), т. Е. Нет ни смежных текстовых узлов, ни пустых текстовых узлов.


По сути, это означает, что следующий XML-элемент

<foo>hello 
wor
ld</foo>

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

Element foo
Text node: ""
Text node: "Hello "
Text node: "wor"
Text node: "ld"

При нормализации узел будет выглядеть следующим образом

Element foo
Text node: "Hello world"

То же самое касается атрибутов: <foo bar="Hello world"/>, комментариев и т.д.

Ответ 2

Проще говоря, нормализация - это сокращение избыточности.

Примеры избыточности:
a) пробелы за пределами тегов root / document(...<document></document>...)
b) пробелы внутри начального тега (<...>) и конечного тега (</...>)
c) пробелы между атрибутами и их значениями (т. е. пробелы между именем ключа и =")
d) лишние объявления пространства имен
e) разрывы строк / пробелы в текстах атрибутов и тегов
f) комментарии и т.д...

Ответ 3

В качестве дополнения к ответу @JBNizet для более технических пользователей вот как выглядит реализация org.w3c.dom.Node интерфейса в com.sun.org.apache.xerces.internal.dom.ParentNode, дающая вам представление о том, как это на самом деле работает.

public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid;
for (kid = firstChild; kid != null; kid = kid.nextSibling) {
kid.normalize();
}
isNormalized(true);
}

Он рекурсивно обходит все узлы и вызывает kid.normalize()
Этот механизм переопределен в org.apache.xerces.dom.ElementImpl

public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid, next;
for (kid = firstChild; kid != null; kid = next) {
next = kid.nextSibling;

// If kid is a text node, we need to check for one of two
// conditions:
// 1) There is an adjacent text node
// 2) There is no adjacent text node, but kid is
// an empty text node.
if ( kid.getNodeType() == Node.TEXT_NODE )
{
// If an adjacent text node, merge it with kid
if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
{
((Text)kid).appendData(next.getNodeValue());
removeChild( next );
next = kid; // Don't advance; there might be another.
}
else
{
// If kid is empty, remove it
if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
removeChild( kid );
}
}
}

// Otherwise it might be an Element, which is handled recursively
else if (kid.getNodeType() == Node.ELEMENT_NODE) {
kid.normalize();
}
}

// We must also normalize all of the attributes
if ( attributes!=null )
{
for( int i=0; i<attributes.getLength(); ++i )
{
Node attr = attributes.item(i);
attr.normalize();
}
}

// changed() will have occurred when the removeChild() was done,
// so does not have to be reissued.

isNormalized(true);
}

Надеюсь, это сэкономит вам немного времени.

2023-10-14 12:03 java xml