자바로 DOM 파싱 정규화-어떻게 작동합니까?


240

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

doc.getDocumentElement().normalize();

왜이 정규화를 수행합니까? 문서를
읽었 지만 단어를 이해할 수 없었습니다.

모든 Text 노드를이 노드 아래에있는 하위 트리의 전체 깊이에 둡니다.

그렇다면 누군가이 나무가 어떻게 보이는지 보여줄 수 있습니까 (사진과 함께)?

왜 정규화가 필요한지 설명해 줄 수 있습니까?
정규화하지 않으면 어떻게됩니까?


에 관계없이 귀하의 질문의 예에 메모를 읽어보십시오 . DOM 파서 속도가 느린 "하고 많은 양의 데이터를 포함하는 XML 문서를로드 할 때 메모리를 많이 소모합니다 그것을위한 솔루션으로 SAX 파서를 고려하시기 바랍니다, SAX는 빠르다 "DOM보다 적은 메모리를 사용합니다." .
wulfgarpro

3
@ wulfgar.pro-나는 당신이 말한 것을 이해합니다. 그러나 질문에 묻은 내용을 이해하고 싶습니다. SAX 구문 분석도 곧 수행 할 것입니다.
Apple Grinder

Google에서 "XML 정규화"를 검색하면 유용한 결과가 나타납니다. 데이터베이스의 정규화와 비슷합니다.
Apple Grinder

2
@ EJP-음 ... XML을 깊이 알지 못하고 그것에 대한 소개 페이지 만 읽기 때문에 여전히 명확하지 않습니다. BTW, 나에게 잘못하지 마라. 당신은 문서 작성자가 평범한 영어 대신 복잡한 단어를 사용하여 정확하게했다. 간단한 단어부터 시작하고 나중에 전문 용어가 더 잘 작동합니다.
Apple Grinder

7
이 글을 쓰는 시점에서 참조 웹 사이트는이 SO 게시물을 참조하고 있습니다. 내 뇌는 의존성 오류를 방금 던졌습니다.
chessofnerd

답변:


366

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

여기서 구조 (예를 들어, 요소, 주석, 처리 명령, 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
아하 ! 지금 훨씬 더 명확합니다. 데이터 구조 (???) 및 노드에 대해 모르겠습니다. 그러나 트리 구조를 간략히 살펴 보았으며 컴퓨터가 제안한 방식으로 "hello world"를 저장할 수 있다고 생각합니다. 맞습니까?
Apple Grinder

9
DOM에 대한 기본 사항을 배워야합니다. 예, DOM은 XML 문서를 트리로 나타냅니다. 그리고 트리에는 자식 노드가있는 루트 노드가 있고, 각 자식 노드에는 자식 노드가 있습니다. 그게 바로 나무입니다. Element는 일종의 노드이고 TextNode는 또 다른 종류의 노드입니다.
JB 니 제트

7
감사합니다 JB Nizet. 지시를받은 후 내가 얼마나 안심했는지 말할 수 없습니다.
Apple Grinder

2
@ user2043553, 줄 바꿈이 실제로 그 지점입니다. 줄 바꿈이 없으면 차이점을 볼 수 없습니다. 이해하지 못했을 경우 : 정규화는 XML을 "수정"하여 하나의 태그가 하나의 요소로 해석됩니다. 그렇게하지 않으면 이러한 줄 바꿈이 동일한 유형의 여러 요소 (같은 태그에 있음) 사이의 구분 기호로 해석 될 수 있습니다.
Stacky

1
@Stacky, 예제에는 두 개의 새로운 줄이 있으며, 예제에서 정규화 한 후에는 표시되지 않으므로 사람들은 더 이상 존재하지 않는다고 믿을 수 있습니다. 줄 바꿈이 표시된 결과 텍스트 노드는 다음과 같습니다. "Hello \ nwor \ nld"정규화는 줄 바꿈을 제거하지 않습니다.
Christian

10

간단히 말해서 정규화는 중복을 줄이는 것입니다.
중복의 예 :
a) 루트 / 문서 태그 외부의 공백 ( ... <document> </ document> ... )
b) 시작 태그 (< ... >) 및 끝 태그 (</ ... >)
c) 속성과 값 사이의 공백 (예 : 키 이름= " 사이의 공백 )
d) 불필요한 네임 스페이스 선언
e) 속성 및 태그 텍스트의 줄 바꿈 / 공백
f) 주석 등 ...


7

더 많은 기술적 인 사용자를위한 @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);
 } 

시간이 절약되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.