余下的句子是:
其中只有结构(例如元素、注释、处理指令、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"/>
,注释等。
简而言之,规范化是减少冗余的过程。
冗余示例:
a) 根/文档标签外的空格(...<document></document>...)
b) 开始标签(<...>)和结束标签(</...>)内的空格
c) 属性及其值之间的空格(即在键名称和=“之间的空格)
d) 多余的命名空间声明
e) 属性和标记文本中的换行符/空格等
f) 注释等...
com.sun.org.apache.xerces.internal.dom.ParentNode
实现 org.w3c.dom.Node
接口的样式,可以让你了解它实际上是如何工作的。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);
}