Помещает все текстовые узлы во всю глубину поддерева под этим узлом
Хорошо, тогда может кто-нибудь показать мне (желательно с картинкой), как выглядит это дерево ?
Кто-нибудь может объяснить мне, зачем нужна нормализация? Что произойдет, если мы не будем нормализовывать?
Переведено автоматически
Ответ 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
publicvoidnormalize() { // 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 elseif (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.