การทำให้เป็นมาตรฐานใน DOM การแยกวิเคราะห์ด้วย java - มันทำงานอย่างไร


240

ฉันเห็นบรรทัดด้านล่างในรหัสสำหรับตัวแยกวิเคราะห์ DOM ที่บทช่วยสอนนี้

doc.getDocumentElement().normalize();

ทำไมเราถึงทำสิ่งนี้ให้เป็นมาตรฐาน?
ฉันอ่านเอกสารแต่ไม่เข้าใจคำ

วางโหนดข้อความทั้งหมดในระดับความลึกเต็มของทรีย่อยที่อยู่ใต้โหนดนี้

โอเคแล้วมีคนแสดงให้ฉันดู (ต้นไม้น่าจะดีกว่า) ต้นไม้ชนิดนี้เป็นอย่างไร

ทุกคนสามารถอธิบายได้ไหมว่าทำไมต้องมีการปรับสภาพให้เป็นมาตรฐาน?
จะเกิดอะไรขึ้นถ้าเราไม่ทำให้ปกติ


โปรดอ่านหมายเหตุในตัวอย่าง: "DOM Parser ช้าและจะใช้หน่วยความจำจำนวนมากเมื่อโหลดเอกสาร XML ซึ่งมีข้อมูลจำนวนมากโปรดพิจารณา SAX parser เป็นวิธีแก้ปัญหา SAX เร็วขึ้น กว่า DOM และใช้หน่วยความจำน้อย " .
wulfgarpro

3
@ wulfgar.pro - ฉันเข้าใจสิ่งที่คุณพูด แต่ฉันต้องการที่จะเข้าใจสิ่งที่ฉันถามในคำถาม ฉันจะทำการแยกวิเคราะห์ SAX ในไม่ช้า
Apple Grinder

การค้นหา google สำหรับ "normalize xml" ให้ผลลัพธ์ที่ดูเหมือนมีประโยชน์ ดูเหมือนว่าจะคล้ายกับการฟื้นฟูในฐานข้อมูล
Apple Grinder

2
@EJP - อืมม ... มันยังไม่ชัดเจนเพราะฉันไม่รู้จัก xml ในเชิงลึกและฉันอ่านหน้าแนะนำเพียงไม่กี่หน้าเท่านั้น BTW ไม่เข้าใจฉันผิดคุณทำสิ่งที่ผู้เขียนเอกสารทำได้ - ใช้คำที่ซับซ้อนแทนภาษาอังกฤษธรรมดา (ธรรมดาเหมือนพนักงานหอก = เข้าใจง่าย) คำง่าย ๆ ก่อนและศัพท์แสงในภายหลังทำงานได้ดีขึ้นสำหรับฉัน
Apple Grinder

7
ตั้งแต่การเขียนเว็บไซต์อ้างอิงนี้อ้างอิงโพสต์ SO นี้ สมองของฉันเพิ่งเกิดข้อผิดพลาดในการพึ่งพา
chessofnerd

คำตอบ:


366

ส่วนที่เหลือของประโยคคือ:

โดยที่โครงสร้างเท่านั้น (เช่นองค์ประกอบความคิดเห็นคำแนะนำในการประมวลผลส่วน CDATA และการอ้างอิงเอนทิตี) แยกโหนดข้อความกล่าวคือไม่มีโหนดข้อความที่อยู่ติดกันและโหนดข้อความเปล่า

ซึ่งโดยทั่วไปหมายความว่าองค์ประกอบ XML ต่อไปนี้

<foo>hello 
wor
ld</foo>

อาจแสดงเช่นนี้ในโหนด denormalized:

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 เป็นแผนผัง และในทรีคุณมีรูตโหนดที่มีโหนดชายด์โหนดชายด์แต่ละโหนดก็มีโหนดลูกเป็นต้นนั่นคือสิ่งที่เป็นต้นไม้ องค์ประกอบเป็นโหนดชนิดหนึ่งและ TextNode เป็นโหนดประเภทอื่น
JB Nizet

7
ขอบคุณ JB Nizet ไม่สามารถบอกคุณได้ว่าฉันรู้สึกผ่อนคลายหลังจากได้รับทิศทาง
Apple Grinder

2
@ user2043553 บรรทัดใหม่เป็นจุดที่มีจริง หากไม่มีบรรทัดใหม่คุณจะไม่เห็นความแตกต่าง หากคุณไม่ควรเข้าใจ: การทำให้เป็นมาตรฐาน "แก้ไข" XML ดังนั้นจึงมีการแปลแท็กหนึ่งแท็กเป็นองค์ประกอบเดียว หากคุณไม่ทำเช่นนั้นอาจเกิดขึ้นได้ว่าการขึ้นบรรทัดใหม่เหล่านี้ถูกตีความเป็นตัวคั่นระหว่างองค์ประกอบหลายประเภทที่เหมือนกัน (resp. ในแท็กเดียวกัน)
Stacky

1
@ Stacky ในตัวอย่างมีสองบรรทัดใหม่พวกเขาจะไม่แสดงหลังจาก normalizing ในตัวอย่างที่อาจทำให้คนเชื่อว่าไม่มีอีกต่อไป โหนดข้อความที่เป็นผลลัพธ์พร้อมการขึ้นบรรทัดใหม่ที่แสดงจะมีลักษณะดังนี้: "Hello \ nwor \ nld" การปรับมาตรฐานไม่ได้ลบบรรทัดใหม่
Christian

10

ง่าย ๆ การทำให้เป็นมาตรฐานคือการลดความซ้ำซ้อน
ตัวอย่างของการทำซ้ำ:
ก) ช่องว่างสีขาวด้านนอกของแท็กรูท / เอกสาร ( ... <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.