source

Java를 사용한 DOM 구문 분석의 정규화 - 어떻게 작동합니까?

goodcode 2022. 7. 30. 19:13
반응형

Java를 사용한 DOM 구문 분석의 정규화 - 어떻게 작동합니까?

이 튜토리얼에서 DOM 파서의 코드로 아래 행을 보았습니다.

doc.getDocumentElement().normalize();

이 정규화를 실시하는 이유는 무엇입니까?
나는 그 문서를 읽었지만 한 마디도 알아들을 수 없었다.

모든 텍스트 노드를 이 노드 아래 하위 트리의 전체 깊이에 배치합니다.

좋아요, 그럼 누가 이 트리가 어떻게 생겼는지 보여줄 수 있나요?

왜 정상화가 필요한지 설명해줄 사람?
정상화하지 않으면 어떻게 되나요?

나머지 문장은 다음과 같습니다.

여기서 구조(예: 요소, 주석, 처리 명령, 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) 루트/스위치 태그(...) 외부에 공백이 있습니다.</filename> </filename>...)
b) 시작 태그(<...>)와 종료 태그(<...>) 내의 공백.>)
c) 속성과 값 사이의 공백( 이름과 =" 사이의 공백)
d) 불필요한 네임스페이스 선언
e) 속성 및 태그 텍스트의 줄 바꿈/공백
f) 코멘트 등...

더 많은 기술 사용자에 대한 @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);
 } 

이것으로 시간을 절약하시길 바랍니다.

언급URL : https://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work

반응형