このチュートリアルで、DOMパーサーのコードに以下の行を表示しました。
doc.getDocumentElement().normalize();
なぜこの正規化を行うのですか?ドキュメント
を読みましたが、言葉が理解できませんでした。
すべてのTextノードを、このノードの下のサブツリーの完全な深さに配置します
さて、誰かがこのツリーがどのように見えるかを(できれば写真で)見せてくれますか?
正規化が必要な理由を誰かが私に説明できますか?
正規化しないとどうなりますか?
このチュートリアルで、DOMパーサーのコードに以下の行を表示しました。
doc.getDocumentElement().normalize();
なぜこの正規化を行うのですか?ドキュメント
を読みましたが、言葉が理解できませんでした。
すべてのTextノードを、このノードの下のサブツリーの完全な深さに配置します
さて、誰かがこのツリーがどのように見えるかを(できれば写真で)見せてくれますか?
正規化が必要な理由を誰かが私に説明できますか?
正規化しないとどうなりますか?
回答:
文の残りの部分は次のとおりです。
構造(要素、コメント、処理命令、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"/>
、コメントなど。
より技術的なユーザー向けの@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);
}
これにより時間を節約できることを願っています。