กำลังแยกวิเคราะห์เอกสาร xml แยกวิเคราะห์ข้อมูล XML การสร้างอินสแตนซ์ตัวแยกวิเคราะห์
การแยกวิเคราะห์ XML เป็นหลักหมายถึงการเดินผ่านเอกสาร XML และส่งคืนข้อมูลที่เกี่ยวข้อง แม้ว่าบริการเว็บจำนวนมากส่งคืนข้อมูลในรูปแบบ JSON แต่ส่วนใหญ่ยังคงใช้ XML ดังนั้นจึงเป็นสิ่งสำคัญที่จะต้องเชี่ยวชาญการแยกวิเคราะห์ XML หากคุณต้องการใช้ API ที่มีอยู่อย่างเต็มรูปแบบ
การใช้ส่วนขยาย SimpleXMLใน PHP ซึ่งเพิ่มกลับมาใน PHP 5.0 การทำงานกับ XML นั้นง่ายและสะดวกมาก ในบทความนี้ ฉันจะแสดงวิธีการทำ
พื้นฐานของการใช้งาน
เริ่มต้นด้วยตัวอย่างต่อไปนี้ languages.xml:
>
>
>
>
เอกสาร XML นี้ประกอบด้วยรายการภาษาการเขียนโปรแกรมพร้อมข้อมูลบางอย่างเกี่ยวกับแต่ละภาษา: ปีที่นำไปใช้และชื่อผู้สร้าง
ขั้นตอนแรกคือการโหลด XML โดยใช้ฟังก์ชันต่างๆ simplexml_load_file(), หรือ simplexml_load_string()- ตามที่ชื่อของฟังก์ชันแนะนำ อันแรกจะโหลด XML จากไฟล์ และอันที่สองจะโหลด XML จากสตริง
ฟังก์ชันทั้งสองอ่านแผนผัง DOM ทั้งหมดลงในหน่วยความจำและส่งกลับวัตถุ SimpleXMLElement- ในตัวอย่างข้างต้น ออบเจ็กต์จะถูกจัดเก็บไว้ในตัวแปร $ languages คุณสามารถใช้ฟังก์ชั่นต่างๆ var_dump()หรือ พิมพ์_r()เพื่อรับรายละเอียดเกี่ยวกับวัตถุที่ส่งคืนหากคุณต้องการ
วัตถุ SimpleXMLElement
[lang] => อาร์เรย์
[ 0 ] => วัตถุ SimpleXMLElement
[@attributes] => อาร์เรย์
[ชื่อ] => ซี
[ปรากฏ] => 1972
[ผู้สร้าง] => เดนนิส ริตชี่
[ 1 ] => วัตถุ SimpleXMLElement
[@attributes] => อาร์เรย์
[ชื่อ] => PHP
[ปรากฏ] => 1995
[ผู้สร้าง] => ราสมุส เลอร์ดอร์ฟ
[ 2 ] => วัตถุ SimpleXMLElement
[@attributes] => อาร์เรย์
[ชื่อ] => ชวา
[ปรากฏ] => 1995
[ผู้สร้าง] => เจมส์ กอสลิง
)
)
XML นี้มีองค์ประกอบราก ภาษาซึ่งภายในมีองค์ประกอบอยู่ 3 ประการ หลางแต่ละองค์ประกอบอาร์เรย์สอดคล้องกับองค์ประกอบ หลางในเอกสาร XML
คุณสามารถเข้าถึงคุณสมบัติของวัตถุโดยใช้ตัวดำเนินการ -> - ตัวอย่างเช่น $ languages->lang จะส่งคืนออบเจ็กต์ SimpleXMLElement ที่ตรงกับองค์ประกอบแรกให้กับคุณ หลาง- วัตถุนี้มีคุณสมบัติสองประการ: ปรากฏ และ ผู้สร้าง
$ ภาษา -> lang [ 0 ] -> ปรากฏ ;
$ภาษา -> lang [ 0 ] -> ผู้สร้าง ;
การแสดงรายการภาษาและการแสดงคุณสมบัติสามารถทำได้ง่ายมากโดยใช้ลูปมาตรฐานเช่น foreach.
foreach ($ภาษา -> lang เป็น $lang ) (
พิมพ์f(
""
,
$lang [ "ชื่อ" ] ,
$lang -> ปรากฏ ,
$lang -> ผู้สร้าง
)
;
}
สังเกตว่าฉันเข้าถึงชื่อแอตทริบิวต์ lang ขององค์ประกอบเพื่อรับชื่อภาษาได้อย่างไร วิธีนี้คุณสามารถเข้าถึงแอตทริบิวต์ใด ๆ ขององค์ประกอบที่แสดงเป็นวัตถุ SimpleXMLElement
การทำงานกับเนมสเปซ
ในขณะที่ทำงานกับ XML ของบริการเว็บต่างๆ คุณจะพบกับเนมสเปซองค์ประกอบมากกว่าหนึ่งครั้ง มาเปลี่ยนของเรากันเถอะ languages.xmlเพื่อแสดงตัวอย่างการใช้เนมสเปซ:
xmlns:dc =>
>
>
>
ตอนนี้องค์ประกอบ ผู้สร้างพอดีกับเนมสเปซ ดีซีซึ่งชี้ไปที่http://purl.org/dc/elements/1.1/ หากคุณพยายามพิมพ์ผู้สร้างภาษาโดยใช้รหัสก่อนหน้าของเรา มันจะไม่ทำงาน ในการอ่านเนมสเปซองค์ประกอบ คุณต้องใช้วิธีใดวิธีหนึ่งต่อไปนี้
วิธีแรกคือการใช้ชื่อ URI โดยตรงในโค้ดเมื่อเข้าถึงเนมสเปซองค์ประกอบ ตัวอย่างต่อไปนี้แสดงวิธีการดำเนินการนี้:
$dc = $ภาษา -> lang [ 1 ] -> เด็ก ๆ( "http://purl.org/dc/elements/1.1/")
;
ก้อง $dc -> ผู้สร้าง ;
วิธี เด็ก()ใช้เนมสเปซและส่งกลับองค์ประกอบลูกที่ขึ้นต้นด้วยคำนำหน้า ต้องใช้สองอาร์กิวเมนต์ ข้อแรกคือเนมสเปซ XML และข้อที่สองคืออาร์กิวเมนต์ทางเลือกซึ่งเป็นค่าเริ่มต้น เท็จ- หากอาร์กิวเมนต์ที่สองถูกตั้งค่าเป็น TRUE เนมสเปซจะถือเป็นคำนำหน้า หากเป็น FALSE เนมสเปซจะถือเป็นเนมสเปซ URL
วิธีที่สองคือการอ่านชื่อ URI จากเอกสารและใช้เมื่อเข้าถึงเนมสเปซองค์ประกอบ นี่เป็นวิธีที่ดีกว่าในการเข้าถึงองค์ประกอบต่างๆ เนื่องจากคุณไม่จำเป็นต้องฮาร์ดโค้ดเป็น URI
$namespaces = $ภาษา -> getNamespaces (จริง) ;
$dc = $ภาษา -> lang [ 1 ] -> เด็ก ( ($เนมสเปซ [ "dc" ] ) ;
ก้อง $dc -> ผู้สร้าง ;
วิธี รับเนมสเปซ()ส่งคืนอาร์เรย์ของชื่อคำนำหน้าและ URI ที่เกี่ยวข้อง ยอมรับพารามิเตอร์เพิ่มเติมซึ่งเป็นค่าเริ่มต้น เท็จ- ถ้าจะตั้งแบบนี้. จริงจากนั้นเมธอดนี้จะส่งคืนชื่อที่ใช้ในโหนดพาเรนต์และโหนดย่อย มิฉะนั้น จะค้นหาเนมสเปซที่ใช้ในโหนดพาเรนต์เท่านั้น
ตอนนี้คุณสามารถวนซ้ำรายการภาษาดังนี้:
$ภาษา = simplexml_load_file ("ภาษา.xml" ) ;
$ns = $ภาษา -> getNamespaces (จริง ) ;
foreach ($ภาษา -> lang เป็น $lang ) (
$dc = $lang -> เด็ก ๆ ($ns [ "dc" ] ) ;
พิมพ์f(
"
%s ปรากฏใน %d และถูกสร้างขึ้นโดย %s
" ,$lang [ "ชื่อ" ] ,
$lang -> ปรากฏ ,
$dc -> ผู้สร้าง
) ;
}
ตัวอย่างการปฏิบัติ - แยกวิเคราะห์ช่องวิดีโอจาก YouTube
ลองดูตัวอย่างที่ได้รับฟีด RSS จาก ช่องยูทูปและแสดงลิงก์ไปยังวิดีโอทั้งหมดจากวิดีโอนั้น เมื่อต้องการทำเช่นนี้ โปรดติดต่อที่อยู่ต่อไปนี้:
http://gdata.youtube.com/feeds/api/users/xxx/uploads
URL ส่งคืนรายการวิดีโอล่าสุดจากช่องที่ระบุในรูปแบบ XML เราจะแยกวิเคราะห์ XML และรับข้อมูลต่อไปนี้สำหรับวิดีโอแต่ละรายการ:
- ลิงค์วิดีโอ
- จิ๋ว
- ชื่อ
เราจะเริ่มต้นด้วยการค้นหาและโหลด XML:
$channel = "ชื่อช่อง" ;
$URL = "http://gdata.youtube.com/feeds/api/users/"- $ช่อง. "/อัพโหลด" ;
$xml = file_get_contents($url);
$feed = simplexml_load_string ($xml) ;
$ns = $feed -> getNameSpaces ( จริง ) ;
หากคุณดูที่ฟีด XML คุณจะเห็นว่ามีหลายองค์ประกอบอยู่ที่นั่น เอนทิตีซึ่งแต่ละร้าน ข้อมูลรายละเอียดเกี่ยวกับวิดีโอเฉพาะจากช่อง แต่เราใช้เฉพาะภาพขนาดย่อ URL ของวิดีโอและชื่อเท่านั้น ธาตุทั้งสามนี้เป็นทายาทของธาตุ กลุ่มซึ่งก็เป็นลูกของ รายการ:
…
…
…
>
…
เราจะผ่านองค์ประกอบทั้งหมด รายการและสำหรับแต่ละรายการเราจะดึงข้อมูลที่จำเป็นออกมา โปรดทราบว่า ผู้เล่น ภาพขนาดย่อและ ชื่ออยู่ในเนมสเปซของสื่อ ดังนั้นเราจึงต้องดำเนินการตามตัวอย่างก่อนหน้านี้ เราได้รับชื่อจากเอกสารและใช้เนมสเปซเมื่อเข้าถึงองค์ประกอบ
foreach ($feed -> รายการเป็น $entry ) (
$group = $entry -> เด็ก ๆ ($ns [ "สื่อ" ] ) ;
$กลุ่ม = $กลุ่ม -> กลุ่ม ;
$thumbnail_attrs = $group -> ภาพขนาดย่อ [ 1 ] -> คุณลักษณะ () ;
$image = $thumbnail_attrs [ "url" ] ;
$player = $group -> ผู้เล่น -> คุณสมบัติ () ;
$link = $player [ "url" ] ;
$title = $group -> ชื่อ ;
พิมพ์f( ""
,
$player, $image, $title);
}
บทสรุป
ตอนนี้คุณรู้วิธีใช้แล้ว SimpleXMLสำหรับการแยกวิเคราะห์ข้อมูล XML คุณสามารถพัฒนาทักษะของคุณได้โดยการแยกวิเคราะห์ฟีด XML ต่างๆ ด้วย API ที่แตกต่างกัน แต่สิ่งสำคัญคือต้องพิจารณาว่า SimpleXML จะอ่าน DOM ทั้งหมดลงในหน่วยความจำ ดังนั้นหากคุณกำลังแยกวิเคราะห์ชุดข้อมูลขนาดใหญ่ หน่วยความจำของคุณอาจไม่เพียงพอ หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ SimpleXML โปรดอ่านเอกสารประกอบ
หากคุณมีคำถามใด ๆ เราขอแนะนำให้ใช้ของเรา
XML Extensible Markup Language คือชุดของกฎสำหรับการเข้ารหัสเอกสารในรูปแบบที่เครื่องอ่านได้ XML เป็นรูปแบบที่นิยมสำหรับการแลกเปลี่ยนข้อมูลบนอินเทอร์เน็ต ไซต์ที่อัปเดตเนื้อหาบ่อยครั้ง เช่น ไซต์ข่าวหรือบล็อก มักจะให้ฟีด XML เพื่อให้โปรแกรมภายนอกทราบถึงการเปลี่ยนแปลงเนื้อหา การส่งและแยกวิเคราะห์ข้อมูล XML เป็นงานทั่วไปสำหรับแอปพลิเคชันที่เชื่อมต่อกับเครือข่าย บทช่วยสอนนี้จะอธิบายวิธีแยกวิเคราะห์เอกสาร XML และใช้ข้อมูล
การเลือกพาร์เซอร์
การวิเคราะห์ช่องทาง
ขั้นตอนแรกในการแยกวิเคราะห์ฟีดคือการตัดสินใจว่าคุณสนใจช่องข้อมูลใด parser แยกฟิลด์ที่กำหนดและละเว้นสิ่งอื่นทั้งหมด
นี่คือตัวอย่างช่องที่จะถูกสำรวจในแอปพลิเคชันตัวอย่าง ทุกโพสต์บน StackOverflow.com จะปรากฏในฟีดเป็นแท็กรายการ ซึ่งมีแท็กย่อยหลายแท็ก:
ฉันมีแอปพลิเคชันที่ต้องใช้ไฟล์ข้อมูล...
แอปพลิเคชันตัวอย่างดึงข้อมูลจากแท็กรายการและชื่อแท็กย่อย ลิงก์ และสรุป
การสร้างอินสแตนซ์ตัวแยกวิเคราะห์
ขั้นตอนต่อไปคือการยกตัวอย่าง parser และเริ่มกระบวนการแยกวิเคราะห์ ตัวอย่างนี้เตรียมใช้งาน parser เพื่อไม่ให้จัดการเนมสเปซและใช้ InputStream ที่ให้มาเป็นอินพุต กระบวนการแยกวิเคราะห์เริ่มต้นด้วยการเรียก nextTag() และเรียกใช้เมธอด readFeed() ซึ่งจะดึงและประมวลผลข้อมูลที่แอปพลิเคชันสนใจ:
คลาสสาธารณะ StackOverflowXmlParser ( // เราไม่ได้ใช้เนมสเปซส่วนตัวคงที่สุดท้าย String ns = null; สาธารณะรายการแยกวิเคราะห์ (InputStream ใน) พ่น XmlPullParserException, IOException ( ลอง ( XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES , false); parser.setInput(in, null); parser.nextTag(); กลับ readFeed(parser) ในที่สุด ( in.close(); ) ... )
หักช่อง
เมธอด readFeed() ทำหน้าที่ประมวลผลฟีดจริง องค์ประกอบที่มีแท็ก "entry" เป็นจุดเริ่มต้นสำหรับการประมวลผลแบบเรียกซ้ำของช่องสัญญาณ หากแท็กถัดไปไม่ใช่แท็กรายการ แท็กนั้นจะถูกข้ามไป หลังจากที่ "ฟีด" ทั้งหมดได้รับการประมวลผลแบบวนซ้ำ readFeed() จะส่งคืนรายการที่มีรายการ (รวมถึงรายการข้อมูลที่ซ้อนกัน) ที่ถูกดึงมาจากฟีด รายการนี้จะถูกส่งกลับโดย parser
รายการส่วนตัว readFeed(XmlPullParser parser) พ่น XmlPullParserException, IOException ( รายการรายการ = new ArrayList (); parser.require(XmlPullParser.START_TAG, ns, "feed"); while (parser.next() != XmlPullParser.END_TAG) ( ถ้า (parser.getEventType() != XmlPullParser.START_TAG) ( Continue; ) String name = parser.getName(); // เริ่มต้นด้วยการค้นหาแท็กรายการ if (name.equals("entry")) ( entry.add( readEntry(parser)); ) else ( ข้าม(parser); ) ) ส่งคืนรายการ;
การแยกวิเคราะห์ XML
ขั้นตอนในการแยกวิเคราะห์ฟีด XML มีดังนี้:
ตัวอย่างนี้แสดงให้เห็นว่า Parser แยกวิเคราะห์รายการ ชื่อ ลิงก์ และสรุปอย่างไร
รายการคลาสคงที่สาธารณะ (ชื่อสตริงสุดท้ายสาธารณะ; ลิงก์สตริงสุดท้ายสาธารณะ; สรุปสตริงสุดท้ายสาธารณะ; รายการส่วนตัว (ชื่อสตริง, สรุปสตริง, ลิงก์สตริง) ( this.title = title; this.summary = summary; this.link = link ; ) ) // แยกวิเคราะห์เนื้อหาของรายการ หากพบชื่อเรื่อง สรุป หรือแท็กลิงก์ ให้ส่งต่อ // ไปยังวิธีการ "อ่าน" ที่เกี่ยวข้องเพื่อการประมวลผล มิฉะนั้น ให้ข้ามแท็ก รายการส่วนตัว readEntry(XmlPullParser parser) พ่น XmlPullParserException, IOException ( parser.require(XmlPullParser.START_TAG, ns, "entry"); String title = null; String summary = null; String link = null; while (parser.next() ! = XmlPullParser.END_TAG) ( if (parser.getEventType() != XmlPullParser.START_TAG) ( Continue; ) String name = parser.getName(); if (name.equals("title")) ( title = readTitle(parser) ; ) else if (name.equals("summary")) ( summary = readSummary(parser); ) else if (name.equals("link")) ( link = readLink(parser); ) else ( ข้าม(parser) ; ) ) ส่งคืนรายการใหม่ (ชื่อ, สรุป, ลิงก์) // ประมวลผลแท็กชื่อในฟีด สตริงส่วนตัว readTitle(XmlPullParser parser) พ่น IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "title"); String title = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "title"); return title; ) // ประมวลผลแท็กลิงก์ในฟีด สตริงส่วนตัว readLink(XmlPullParser parser) พ่น IOException, XmlPullParserException ( String link = ""; parser.require(XmlPullParser.START_TAG, ns, "link"); String tag = parser.getName(); String relType = parser.getAttributeValue(null , "rel"); if (tag.equals("link")) ( if (relType.equals("alternate"))( link = parser.getAttributeValue(null, "href"); parser.nextTag(); ) ) parser.require(XmlPullParser.END_TAG, ns, "link"); return link) // ประมวลผลแท็กสรุปในฟีด สตริงส่วนตัว readSummary(XmlPullParser parser) ส่ง IOException, XmlPullParserException ( parser.require(XmlPullParser.START_TAG, ns, "summary"); String summary = readText(parser); parser.require(XmlPullParser.END_TAG, ns, "summary"); return summary; ) // สำหรับชื่อแท็กและสรุป ให้แยกค่าข้อความออกมา สตริงส่วนตัว readText(XmlPullParser parser) พ่น IOException, XmlPullParserException ( String result = ""; if (parser.next() == XmlPullParser.TEXT) ( result = parser.getText(); parser.nextTag(); ) ส่งคืนผลลัพธ์; ) ... )
ข้ามรายการที่คุณไม่ต้องการ
ในขั้นตอนหนึ่งของการแยกวิเคราะห์ XML ที่อธิบายไว้ข้างต้น parser จะข้ามแท็กที่เราไม่สนใจ ด้านล่างนี้เป็นโค้ดพาร์เซอร์สำหรับวิธีการข้าม ():
ข้ามโมฆะส่วนตัว (XmlPullParser parser) พ่น XmlPullParserException, IOException ( if (parser.getEventType() != XmlPullParser.START_TAG) ( Throw new IllegalStateException(); ) int deep = 1; while (deep != 0) ( switch (parser. ถัดไป()) ( case XmlPullParser.END_TAG: deep--; break; case XmlPullParser.START_TAG: deep++; break; ) ) )
นี่คือวิธีการทำงาน:
- เมธอดนี้จะส่งข้อยกเว้นหากเหตุการณ์ปัจจุบันไม่ใช่ START_TAG
- ใช้ START_TAG และเหตุการณ์ทั้งหมดไม่เกิน END_TAG
- เพื่อให้แน่ใจว่าหยุดที่ END_TAG ที่ถูกต้องและไม่ใช่แท็กแรกหลังจาก START_TAG เดิม แท็กนี้จะติดตามความลึกที่ซ้อนกัน
ดังนั้น หากองค์ประกอบปัจจุบันมีองค์ประกอบที่ซ้อนกัน ค่าความลึกจะไม่เป็น 0 จนกว่าโปรแกรมแยกวิเคราะห์จะประมวลผลเหตุการณ์ทั้งหมดระหว่าง START_TAG ดั้งเดิมและ END_TAG ที่เกี่ยวข้อง ตัวอย่างเช่น พิจารณาว่าเครื่องวิเคราะห์ผ่านไปอย่างไร
- ในการผ่านครั้งแรกผ่านลูป while แท็กถัดไปที่เครื่องวิเคราะห์พบหลังจากนั้น
นี่คือ START_TAG สำหรับ - ในการผ่านครั้งที่สองผ่านลูป while แท็กถัดไปที่เครื่องวิเคราะห์พบคือ END_TAG
- ในการผ่านครั้งที่สามผ่านลูป while แท็กถัดไปที่เครื่องวิเคราะห์พบคือ START_TAG
- ค่าความลึกเพิ่มขึ้นเป็น 2 - ในการผ่านครั้งที่สี่ผ่านลูป while แท็กถัดไปที่เครื่องวิเคราะห์พบคือ END_TAG- ค่าความลึกจะลดลงเหลือ 1
- ในการผ่านครั้งที่ห้าซึ่งเป็นครั้งสุดท้ายผ่านลูป while แท็กถัดไปที่เครื่องวิเคราะห์พบคือ END_TAG- ค่าความลึกจะลดลงเหลือ 0 ซึ่งแสดงว่า
ข้ามองค์ประกอบสำเร็จแล้ว
การประมวลผลข้อมูลเอ็กซ์เอ็มแอล
แอปพลิเคชันตัวอย่างได้รับและแยกวิเคราะห์ฟีด XML ใน AsyncTask การประมวลผลเกิดขึ้นภายนอกเธรด UI หลัก เมื่อการประมวลผลเสร็จสิ้น แอปพลิเคชันจะอัปเดตอินเทอร์เฟซผู้ใช้ในกิจกรรมหลัก (NetworkActivity)
ในตัวอย่างด้านล่าง เมธอด loadPage() จะดำเนินการดังต่อไปนี้:
- เริ่มต้นตัวแปรสตริงด้วย URL ที่ชี้ไปยังฟีด XML
- หากการตั้งค่าผู้ใช้และการเชื่อมต่อเครือข่ายอนุญาต ให้เรียก new DownloadXmlTask().execute(url) สิ่งนี้จะสร้างออบเจ็กต์ DownloadXmlTask ใหม่ (คลาสย่อย AsyncTask) และดำเนินการวิธีการดำเนินการ () ซึ่งจะดาวน์โหลดและแยกวิเคราะห์ไปป์และส่งกลับผลลัพธ์สตริงที่จะแสดงใน UI
- doInBackground() ดำเนินการเมธอด loadXmlFromNetwork() โดยจะส่ง URL ของช่องเป็นพารามิเตอร์ วิธีการ loadXmlFromNetwork() รับและประมวลผลช่องสัญญาณ เมื่อเสร็จสิ้นการประมวลผล ก็จะส่งกลับสตริงผลลัพธ์
- onPostExecute() รับสตริงที่ส่งคืนและแสดงใน UI
ด้านล่างนี้คือเมธอด loadXmlFromNetwork() ซึ่งเรียกจาก DownloadXmlTask มันทำดังต่อไปนี้:
- สร้างอินสแตนซ์ของ StackOverflowXmlParser นอกจากนี้ยังสร้างตัวแปรสำหรับออบเจ็กต์รายการ และชื่อ , url และสรุป เพื่อจัดเก็บค่าที่แยกจากฟีด XML สำหรับฟิลด์เหล่านี้
- เรียก downloadUrl() ซึ่งจะดาวน์โหลดช่องและส่งกลับเป็น InputStream
- ใช้ StackOverflowXmlParser เพื่อแยกวิเคราะห์ InputStream StackOverflowXmlParser เติมข้อมูลในรายการด้วยข้อมูลจากฟีด
- ประมวลผลรายการ และรวมข้อมูลช่องเข้ากับมาร์กอัป HTML
- ส่งกลับสตริง HTML ที่แสดงใน UI ของกิจกรรมหลัก AsyncTask ในเมธอด onPostExecute()
ชื่อสตริง = null;
URL สตริง = null; สรุปสตริง = null;ปฏิทินทันที = Calendar.getInstance();ตัวจัดรูปแบบ DateFormat = SimpleDateFormat ใหม่ ("MMM dd h:mmaa");
"); // หากผู้ใช้ตั้งค่ากำหนดให้รวมข้อความสรุป // เพิ่มลงในจอแสดงผล ถ้า (pref) ( htmlString.append(entry.summary); ) ) กลับ htmlString.toString(); ) // กำหนดการแสดงสตริงของ URL ให้ตั้งค่าการเชื่อมต่อและรับ // สตรีมอินพุต ส่วนตัว InputStream downloadUrl (String urlString) พ่น IOException ( URL url = new URL(urlString); HttpURLConnection conn = (HttpURLConnection) url.openConnection() ; conn.setReadTimeout(10,000 /* มิลลิวินาที */); conn.setConnectTimeout(15000 /* มิลลิวินาที */); conn.setRequestMethod("GET"); // เริ่มการสืบค้น conn.connect( ); );ผู้เขียน : อาร์เซนี คาพูลไคน์
วันที่เผยแพร่: 21 กันยายน 2555
แปล: อ. ภานิน
วันที่แปล: 10 พฤศจิกายน 2556
การแนะนำ
XML เป็นภาษามาร์กอัปมาตรฐานที่ระบุชุดกฎสำหรับการเข้ารหัสเอกสารที่มีโครงสร้างแบบลำดับชั้นในรูปแบบข้อความที่มนุษย์สามารถอ่านได้ มาตรฐาน XML แพร่หลายและใช้เพื่อสร้างทั้งเอกสารธรรมดาที่มีขนาดกะทัดรัดมาก (เช่น คำขอ SOAP) และเอกสารหลายกิกะไบต์ (ใช้โดยโครงการ OpenStreetMap) ที่มีการพึ่งพาข้อมูลที่ซับซ้อน (COLLADA) ในการประมวลผลเอกสาร XML โดยทั่วไปผู้ใช้จำเป็นต้องมีไลบรารีพิเศษ: ต้องใช้ตัวแยกวิเคราะห์เอกสาร XML ที่แปลงเอกสารจากเอกสารต้นฉบับเป็นการนำเสนอภายใน มาตรฐาน XML เป็นการแลกเปลี่ยนในแง่ของความเร็วในการแยกวิเคราะห์ ความสามารถในการอ่านของผู้ใช้ และความซับซ้อนของโค้ดในการแยกวิเคราะห์ ดังนั้น การมีระบบที่รวดเร็วสำหรับการแยกวิเคราะห์เอกสาร XML อาจส่งผลต่อตัวเลือก XML ที่ต้องการเป็นรูปแบบสำหรับการจัดเก็บข้อมูลแอปพลิเคชัน
บทนี้อธิบายเทคนิคต่างๆ ที่มุ่งปรับปรุงประสิทธิภาพของระบบการแยกวิเคราะห์ที่อธิบายไว้ และช่วยให้ผู้เขียนพัฒนาระบบการแยกวิเคราะห์ที่มีประสิทธิผลอย่างมากโดยใช้ภาษาการเขียนโปรแกรม C++: pugixml แม้ว่าเทคนิคเหล่านี้จะใช้สำหรับระบบแยกวิเคราะห์เอกสาร XML แต่ส่วนใหญ่สามารถนำไปใช้ในระบบแยกวิเคราะห์เอกสารในรูปแบบอื่น หรือแม้แต่ในส่วนประกอบซอฟต์แวร์ที่ไม่เกี่ยวข้องโดยสิ้นเชิง (ตัวอย่างเช่น อัลกอริธึมการจัดการหน่วยความจำใช้กันอย่างแพร่หลายในพื้นที่ระบบแยกวิเคราะห์เอกสารข้อความที่ไม่เกี่ยวข้อง) .
เนื่องจากมีแนวทางที่แตกต่างกันอย่างกว้างขวางหลายวิธีในการแยกวิเคราะห์เอกสาร XML และระบบการแยกวิเคราะห์ต้องดำเนินการขั้นตอนเพิ่มเติมที่แม้แต่ผู้ที่คุ้นเคยกับเอกสาร XML จะไม่ทราบ จึงเป็นสิ่งสำคัญที่จะต้องอธิบายงานที่มีอยู่ก่อนก่อนที่จะลงรายละเอียดเกี่ยวกับรายละเอียดการใช้งาน
รูปแบบของระบบการแยกวิเคราะห์ XML
ระบบแยกวิเคราะห์ XML แต่ละรุ่นจะเหมาะสมที่สุดในบางสถานการณ์ และแต่ละรุ่นก็มีประสิทธิภาพและพารามิเตอร์การใช้หน่วยความจำของตัวเอง รุ่นต่อไปนี้ใช้กันอย่างแพร่หลาย:
- เมื่อใช้ระบบแยกวิเคราะห์แบบ SAX (Simple API สำหรับ XML) ผู้ใช้จะเห็นส่วนประกอบซอฟต์แวร์ที่คาดว่าสตรีมข้อมูลเอกสารเป็นอินพุต และมีฟังก์ชันเรียกกลับหลายอย่าง เช่น "แท็กเปิด", "แท็กปิด", "อักขระ แท็กภายใน" ระบบแยกวิเคราะห์ใช้ฟังก์ชันโทรกลับขณะประมวลผลข้อมูลเอกสาร บริบทที่จำเป็นสำหรับการแยกวิเคราะห์ถูกจำกัดโดยความลึกของแผนผังขององค์ประกอบปัจจุบัน ซึ่งแสดงถึงความต้องการหน่วยความจำที่ลดลงอย่างมาก ระบบแยกวิเคราะห์ประเภทนี้สามารถใช้เพื่อประมวลผลเอกสารที่สตรีมเมื่อมีเอกสารเพียงบางส่วนเท่านั้นในแต่ละครั้ง
- การแยกวิเคราะห์แบบดึงนั้นคล้ายกับการแยกวิเคราะห์แบบ SAX ในแง่ของกระบวนการ - องค์ประกอบเอกสารหนึ่งรายการได้รับการประมวลผลในแต่ละครั้ง แต่วิธีการจัดการกระบวนการแยกวิเคราะห์มีการเปลี่ยนแปลง: ในระบบการแยกวิเคราะห์แบบ SAX กระบวนการแยกวิเคราะห์จะถูกควบคุมโดย ระบบเองโดยใช้ฟังก์ชันการโทรกลับ ในขณะที่อยู่ในการแยกวิเคราะห์แบบดึง ผู้ใช้จะควบคุมกระบวนการแยกวิเคราะห์โดยใช้อ็อบเจ็กต์ที่คล้ายตัววนซ้ำ
- เมื่อใช้ระบบการแยกวิเคราะห์ที่ใช้ DOM (Document Object Model) ผู้ใช้จะส่งผ่านระบบการแยกวิเคราะห์เอกสารที่สมบูรณ์ในรูปแบบของบัฟเฟอร์หรือกระแสข้อมูลข้อความ โดยขึ้นอยู่กับว่าระบบการแยกวิเคราะห์สร้างการแสดงวัตถุในหน่วยความจำของทั้งหมด แผนผังขององค์ประกอบเอกสาร โดยใช้อ็อบเจ็กต์แยกกันสำหรับแต่ละองค์ประกอบหรือแอตทริบิวต์ XML เฉพาะ และชุดของการดำเนินการที่ถูกต้อง (เช่น "รับลูกทั้งหมดของโหนดนี้") ไลบรารี pugxml ใช้โมเดลนี้
การเลือกโมเดลระบบการแยกวิเคราะห์มักจะขึ้นอยู่กับขนาดของเอกสารและโครงสร้างของเอกสาร เนื่องจาก pugixml แยกวิเคราะห์ตาม DOM จึงมีประสิทธิภาพสำหรับเอกสารที่:
- มีขนาดเล็กมากจนสามารถใส่ลงในหน่วยความจำได้อย่างสมบูรณ์
- มีโครงสร้างที่ซับซ้อนพร้อมการเชื่อมโยงระหว่างโหนดที่ต้องสำรวจหรือ
- ต้องการการแปลงเอกสารที่ซับซ้อน
โซลูชันทางสถาปัตยกรรมใน pugixml
ในระหว่างการพัฒนาไลบรารี pugixml จุดสนใจส่วนใหญ่อยู่ที่ปัญหาของการสร้างการแสดง DOM เนื่องจากถึงแม้จะมีระบบแยกวิเคราะห์ที่ใช้ SAX ที่รวดเร็วและมีน้ำหนักเบา (เช่น Expat) ก็พร้อมใช้งาน แต่ระบบแยกวิเคราะห์ XML บน DOM ทั้งหมดก็พร้อมใช้งานสำหรับการผลิต การใช้งานในขณะที่สร้าง pugixml (2549) นั้นไม่เบาเกินไปหรือไม่เร็วเกินไป ตามนี้ เป้าหมายหลักของกระบวนการพัฒนา puixml คือการสร้างไลบรารีที่รวดเร็วและมีน้ำหนักเบาสำหรับดำเนินการจัดการเอกสาร XML บน DOM
อนุญาตให้ตีพิมพ์บทความนี้ได้เฉพาะเมื่อมีลิงก์ไปยังเว็บไซต์ของผู้เขียนบทความเท่านั้น
ในบทความนี้ ฉันจะแสดงตัวอย่างวิธีแยกวิเคราะห์ไฟล์ XML ขนาดใหญ่ หากเซิร์ฟเวอร์ของคุณ (โฮสติ้ง) ไม่ได้ห้ามไม่ให้เพิ่มเวลาการทำงานของสคริปต์ คุณสามารถแยกวิเคราะห์ไฟล์ XML ที่มีน้ำหนักอย่างน้อยกิกะไบต์ โดยส่วนตัวแล้วฉันจะแยกวิเคราะห์เฉพาะไฟล์จากโอโซนที่มีน้ำหนัก 450 เมกะไบต์เท่านั้น
เมื่อแยกวิเคราะห์ไฟล์ XML ขนาดใหญ่ เกิดปัญหาสองประการ:
1. หน่วยความจำไม่เพียงพอ
2. มีเวลาจัดสรรไม่เพียงพอสำหรับให้สคริปต์ทำงาน
ปัญหาที่สองตามเวลาสามารถแก้ไขได้หากเซิร์ฟเวอร์ไม่ห้าม
แต่ปัญหาเกี่ยวกับหน่วยความจำนั้นแก้ไขได้ยากแม้ว่าเราจะพูดถึงเซิร์ฟเวอร์ของคุณเองก็ตาม การย้ายไฟล์ขนาด 500 เมกะไบต์นั้นไม่ใช่เรื่องง่าย และไม่สามารถเพิ่มหน่วยความจำบนโฮสต์และ VDS ได้
PHP มีตัวเลือกการประมวลผล XML ในตัวมากมาย - SimpleXML, DOM, SAX
ตัวเลือกทั้งหมดเหล่านี้มีการอธิบายโดยละเอียดในบทความหลายบทความพร้อมตัวอย่าง แต่ตัวอย่างทั้งหมดแสดงให้เห็นถึงการทำงานกับเอกสาร XML แบบเต็ม
นี่คือตัวอย่างหนึ่ง รับวัตถุจากไฟล์ XML
$xml = simplexml_load_file ("1.xml" ); ?>
ตอนนี้คุณสามารถประมวลผลวัตถุนี้ได้ แต่...
อย่างที่คุณเห็น ไฟล์ XML ทั้งหมดจะถูกอ่านในหน่วยความจำ จากนั้นทุกอย่างจะถูกแยกวิเคราะห์เป็นออบเจ็กต์
นั่นคือข้อมูลทั้งหมดจะเข้าสู่หน่วยความจำ และหากมีหน่วยความจำที่จัดสรรไม่เพียงพอ สคริปต์จะหยุดทำงาน
ตัวเลือกนี้ไม่เหมาะสำหรับการประมวลผลไฟล์ขนาดใหญ่ คุณต้องอ่านไฟล์ทีละบรรทัดและประมวลผลข้อมูลนี้ทีละรายการ
ในกรณีนี้ การตรวจสอบความถูกต้องจะดำเนินการในขณะที่ข้อมูลถูกประมวลผล ดังนั้นคุณต้องสามารถย้อนกลับได้ เช่น ลบข้อมูลทั้งหมดที่ป้อนลงในฐานข้อมูลในกรณีของไฟล์ XML ที่ไม่ถูกต้อง หรือดำเนินการสองรอบ ผ่านไฟล์ ขั้นแรกให้อ่านเพื่อตรวจสอบความถูกต้อง จากนั้นจึงอ่านเพื่อประมวลผลข้อมูล
ต่อไปนี้เป็นตัวอย่างทางทฤษฎีของการแยกวิเคราะห์ไฟล์ XML ขนาดใหญ่
สคริปต์นี้จะอ่านอักขระทีละตัวจากไฟล์ รวบรวมข้อมูลนี้ลงในบล็อก และส่งไปยังตัวแยกวิเคราะห์ XML
วิธีการนี้แก้ปัญหาหน่วยความจำได้อย่างสมบูรณ์และไม่ทำให้เกิดภาระ แต่จะทำให้ปัญหารุนแรงขึ้นเมื่อเวลาผ่านไป วิธีพยายามแก้ไขปัญหาเมื่อเวลาผ่านไป โปรดอ่านด้านล่าง
ฟังก์ชั่น webi_xml ($ไฟล์)
{
########
### ฟังก์ชั่นข้อมูล
{
พิมพ์ $data ;
}
############################################
{
พิมพ์ $ชื่อ ;
print_r($attrs);
}
## ฟังก์ชั่นแท็กปิด
ฟังก์ชั่น endElement ($parser, $name)
{
พิมพ์ $ชื่อ ;
}
############################################
($xml_parser, "ข้อมูล");
//เปิดไฟล์
$fp = fopen($file, "r");
$perviy_vxod = 1 ; $ข้อมูล = "" ;
{
$simvol = fgetc ($fp); $data .= $simvol ;
if($simvol != ">" ) ( ดำเนินการต่อ;)
"
);
$perviy_vxod
=
0
;}
เสียงสะท้อน "
หยุดพัก;
}
$ข้อมูล = "" ;
}
fclose($fp);
Webi_xml("1.xml");
?>
ในตัวอย่างนี้ ฉันรวมทุกอย่างไว้ในฟังก์ชันเดียว webi_xml() และที่ด้านล่างสุด คุณจะเห็นการเรียกของมัน
สคริปต์ประกอบด้วยฟังก์ชันหลักสามประการ:
1. ฟังก์ชั่นที่จับการเปิดแท็ก startElement()
2. ฟังก์ชั่นที่จับแท็กปิด endElement()
3. และฟังก์ชั่นการรับ ข้อมูล()
.
สมมติว่าเนื้อหาของไฟล์ 1.xml เป็นสูตร
<
title
>ขนมปังธรรมดา
title
>
<
ingredient amount
=
"3"
unit
=
"стакан"
>แป้ง
ingredient
>
<
ingredient amount
=
"0.25"
unit
=
"грамм"
>ยีสต์
ingredient
>
<
ingredient amount
=
"1.5"
unit
=
"стакан"
>น้ำอุ่น
ingredient
>
<
ingredient amount
=
"1"
unit
=
"чайная ложка"
>เกลือ
ingredient
>
<
instructions
>
<
step
>
ผสมส่วนผสมทั้งหมดแล้วนวดให้ละเอียด.
step
>
<
step
>
คลุมด้วยผ้าแล้วทิ้งไว้หนึ่งชั่วโมงในห้องอุ่น.
step
>
<
step
>
นวดอีกครั้ง,
วางบนถาดอบแล้วนำเข้าเตาอบ.
step
>
<
step
>
เยี่ยมชมเว็บไซต์
step
>
instructions
>
recipe
>
เราเริ่มต้นด้วยความท้าทาย ฟังก์ชั่นทั่วไป webi_xml("1.xml");
จากนั้น parser จะเริ่มทำงานในฟังก์ชันนี้และแปลงชื่อแท็กทั้งหมดให้เป็นตัวพิมพ์ใหญ่ เพื่อให้แท็กทั้งหมดมีตัวพิมพ์เหมือนกัน
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, จริง);
ตอนนี้เราระบุแล้วว่าฟังก์ชันใดจะทำงานเพื่อจับการเปิดแท็ก การปิด และการประมวลผลข้อมูล
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_Character_data_handler($xml_parser, "ข้อมูล");
ถัดมาคือการเปิดไฟล์ที่ระบุ โดยวนซ้ำไฟล์ทีละอักขระ จากนั้นอักขระแต่ละตัวจะถูกเพิ่มลงในตัวแปรสตริงจนกว่าจะพบอักขระ >
.
หากนี่เป็นการเข้าถึงไฟล์ครั้งแรกทุกอย่างที่ไม่จำเป็นในตอนต้นของไฟล์จะถูกลบไปตลอดทางทุกสิ่งที่อยู่ก่อนหน้า
นี่คือแท็กที่ XML ควรขึ้นต้นด้วย
เป็นครั้งแรกที่ตัวแปรสตริงจะมีสตริง
และส่งไปยังเครื่องถอดประกอบ
xml_parse ($xml_parser, $data, feof ($fp));
หลังจากประมวลผลข้อมูลแล้ว ตัวแปรสตริงจะถูกรีเซ็ต และการรวบรวมข้อมูลลงในสตริงจะเริ่มต้นอีกครั้ง และสตริงจะถูกสร้างขึ้นเป็นครั้งที่สอง
ในวันที่สาม
ในวันที่สี่
ขนมปังธรรมดา
โปรดทราบว่าตัวแปรสตริงจะถูกสร้างขึ้นจากแท็กที่เสร็จสมบูรณ์เสมอ >
และไม่จำเป็นต้องส่งแท็กเปิดและปิดพร้อมข้อมูลให้โจร เป็นต้น
เป็นสิ่งสำคัญที่ตัวจัดการนี้จะต้องได้รับแท็กที่ไม่ขาดตอนทั้งหมด แท็กที่เปิดอยู่อย่างน้อยหนึ่งแท็ก และในขั้นตอนต่อไปแท็กที่ปิด หรือรับไฟล์ 1,000 บรรทัดทันที ไม่สำคัญ สิ่งสำคัญคือแท็ก ไม่แตกเช่น
เลอ>ขนมปังธรรมดา
ด้วยวิธีนี้ คุณจะไม่สามารถส่งข้อมูลไปยังตัวจัดการได้ เนื่องจากแท็กขาด
คุณสามารถคิดวิธีการส่งข้อมูลไปยังตัวจัดการของคุณเองได้ เช่น รวบรวมข้อมูล 1 เมกะไบต์ และส่งไปยังตัวจัดการเพื่อเพิ่มความเร็ว เพียงตรวจสอบให้แน่ใจว่าแท็กนั้นสมบูรณ์อยู่เสมอ และข้อมูลสามารถฉีกขาดได้
ขนมปัง
จึงสามารถส่งเป็นอะไหล่ได้ตามใจชอบ ไฟล์ขนาดใหญ่ถึงผู้จัดการ
ตอนนี้เรามาดูวิธีการประมวลผลข้อมูลนี้และวิธีรับข้อมูล
เริ่มต้นด้วยฟังก์ชันแท็กเปิด startElement ($พาร์เซอร์, $ชื่อ, $attrs)
สมมติว่าการประมวลผลถึงบรรทัดแล้ว
<
ingredient amount
=
"3"
unit
=
"стакан"
>แป้ง
ingredient
>
จากนั้นภายในฟังก์ชัน ตัวแปร $name จะเท่ากับ วัตถุดิบนั่นคือชื่อของแท็กที่เปิดอยู่ (ยังไม่ได้มาปิดแท็ก)
นอกจากนี้ ในกรณีนี้ อาร์เรย์ของแอตทริบิวต์ของแท็ก $attrs จะพร้อมใช้งาน ซึ่งจะมีข้อมูล จำนวน = "3" และหน่วย = "แก้ว".
หลังจากนั้น ฟังก์ชันจะประมวลผลข้อมูลของแท็กที่เปิดอยู่ ข้อมูล ($พาร์เซอร์, $data)
ตัวแปร $data จะมีทุกอย่างที่อยู่ระหว่างแท็กเปิดและแท็กปิด ในกรณีของเราคือข้อความ Muka
และการประมวลผลสตริงของเราโดยฟังก์ชันจะสิ้นสุดลง endElement ($พาร์เซอร์, $ชื่อ)
นี่คือชื่อของแท็กที่ปิด ในกรณีของเรา $name จะเท่ากับ วัตถุดิบ
และหลังจากนั้นทุกอย่างก็กลับเป็นวงกลมอีกครั้ง
ตัวอย่างข้างต้นแสดงให้เห็นเฉพาะหลักการของการประมวลผล XML เท่านั้น แต่สำหรับการใช้งานจริงจำเป็นต้องได้รับการแก้ไข
โดยทั่วไป คุณจะต้องแยกวิเคราะห์ XML ขนาดใหญ่เพื่อป้อนข้อมูลลงในฐานข้อมูล และเพื่อประมวลผลข้อมูลอย่างเหมาะสม คุณจำเป็นต้องทราบว่าข้อมูลเป็นของแท็กที่เปิดอยู่ ระดับใดของการซ้อนแท็ก และแท็กใดที่เปิดอยู่ในลำดับชั้นด้านบน ด้วยข้อมูลนี้ คุณสามารถประมวลผลไฟล์ได้อย่างถูกต้องโดยไม่มีปัญหาใดๆ
ในการดำเนินการนี้ คุณต้องแนะนำตัวแปรร่วมหลายตัวที่จะรวบรวมข้อมูลเกี่ยวกับแท็กที่เปิด การซ้อน และข้อมูล
นี่คือตัวอย่างที่คุณสามารถใช้ได้
ฟังก์ชั่น webi_xml ($ไฟล์)
{
$webi_ความลึกทั่วโลก ; // เคาน์เตอร์เพื่อติดตามความลึกของการซ้อน
$เว็บบี_ความลึก = 0 ;
$webi_tag_open ทั่วโลก ; // จะมีอาร์เรย์ของ open in ในขณะนี้แท็ก
$webi_tag_open = array();
$webi_data_temp ทั่วโลก ; // อาร์เรย์นี้จะมีข้อมูลของแท็กเดียว
####################################################
### ฟังก์ชั่นข้อมูล
ข้อมูลฟังก์ชัน ($parser, $data)
{
$webi_ความลึกทั่วโลก ;
$webi_tag_open ทั่วโลก ;
$webi_data_temp ทั่วโลก ;
// เพิ่มข้อมูลลงในอาร์เรย์ที่ระบุการซ้อนและแท็กที่เปิดอยู่ในปัจจุบัน
$webi_data_temp [ $webi_เจาะลึก ][ $webi_tag_open [ $webi_เจาะลึก ]][ "ข้อมูล" ].= $data ;
}
############################################
####################################################
### ฟังก์ชั่นเปิดแท็ก
ฟังก์ชั่น startElement ($parser, $name, $attrs)
{
$webi_ความลึกทั่วโลก ;
$webi_tag_open ทั่วโลก ;
$webi_data_temp ทั่วโลก ;
// หากระดับการซ้อนไม่เป็นศูนย์อีกต่อไป แสดงว่าแท็กหนึ่งเปิดอยู่แล้ว
// และข้อมูลจากข้อมูลนั้นอยู่ในอาร์เรย์แล้ว คุณสามารถประมวลผลได้
ถ้า ($webi_ความลึก)
{
"
;
พิมพ์ "
"
;
print_r($webi_tag_open); // อาร์เรย์ของแท็กที่เปิดอยู่
พิมพ์ "
" ;
// หลังจากประมวลผลข้อมูลแล้ว ให้ลบออกเพื่อเพิ่มหน่วยความจำ
unset($GLOBALS [ "webi_data_temp" ][ $webi_ledge ]);
}
// ขณะนี้แท็กถัดไปถูกเปิดขึ้น และการประมวลผลเพิ่มเติมจะเกิดขึ้นในขั้นตอนถัดไป
$webi_ความลึก++; // เพิ่มการซ้อน
$webi_tag_open [ $webi_ledge ]= $name ; // เพิ่มแท็กเปิดลงในอาร์เรย์ข้อมูล
$webi_data_temp [ $webi_เจาะลึก ][ $name ][ "attrs" ]= $attrs ; // ตอนนี้เพิ่มแอตทริบิวต์แท็ก
}
###############################################
#################################################
## ฟังก์ชั่นแท็กปิด
ฟังก์ชั่น endElement ($parser, $name) (
$webi_ความลึกทั่วโลก ;
$webi_tag_open ทั่วโลก ;
$webi_data_temp ทั่วโลก ;
// การประมวลผลข้อมูลเริ่มต้นที่นี่ เช่น การเพิ่มฐานข้อมูล บันทึกลงในไฟล์ เป็นต้น
// $webi_tag_open ประกอบด้วยแท็กที่เปิดต่อเนื่องกันตามระดับการซ้อน
// ตัวอย่างเช่น $webi_tag_open[$webi_ledge] มีชื่อของแท็กที่เปิดซึ่งข้อมูลกำลังถูกประมวลผลอยู่
// ระดับการซ้อนแท็ก $webi_deep
// $webi_data_temp[$webi_length][$webi_tag_open[$webi_ allowance]]["attrs"] อาร์เรย์ของแอตทริบิวต์ของแท็ก
// $webi_data_temp[$webi_length][$webi_tag_open[$webi_ allowance]]["data"] ข้อมูลแท็ก
พิมพ์ "ข้อมูล" . $webi_tag_open [ $webi_ความลึก ]. "--" .($webi_data_temp [ $webi_เจาะลึก ][ $webi_tag_open [ $webi_เจาะลึก ]][ "ข้อมูล" ]) -
"
;
print_r ($webi_data_temp [ $webi_เจาะลึก ][ $webi_tag_open [ $webi_เจาะลึก ]][ "attrs" ]);
พิมพ์ "
"
;
print_r($webi_tag_open);
พิมพ์ "
" ;
ยกเลิกการตั้งค่า($GLOBALS [ "webi_data_temp" ]); // หลังจากประมวลผลข้อมูลแล้ว เราจะลบอาร์เรย์ที่มีข้อมูลทั้งหมด เนื่องจากแท็กถูกปิด
unset($GLOBALS [ "webi_tag_open" ][ $webi_ledge ]); // ลบข้อมูลเกี่ยวกับแท็กที่เปิดนี้... เนื่องจากปิดไปแล้ว
$webi_ความลึก --; //ลดการซ้อน
}
############################################
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, จริง);
// ระบุว่าฟังก์ชันใดจะทำงานเมื่อเปิดและปิดแท็ก
xml_set_element_handler($xml_parser, "startElement", "endElement");
// ระบุฟังก์ชันสำหรับการทำงานกับข้อมูล
xml_set_Character_data_handler($xml_parser, "ข้อมูล");
//เปิดไฟล์
$fp = fopen($file, "r");
$perviy_vxod = 1 ; // ตั้งค่าสถานะเพื่อตรวจสอบรายการแรกในไฟล์
$ข้อมูล = "" ; // ที่นี่เรารวบรวมข้อมูลจากไฟล์เป็นส่วนๆ และส่งไปยังตัวแยกวิเคราะห์ xml
// วนซ้ำจนกว่าจะพบจุดสิ้นสุดของไฟล์
ในขณะที่ (! feof ($fp ) และ $fp )
{
$simvol = fgetc ($fp); // อ่านอักขระหนึ่งตัวจากไฟล์
$data .= $simvol ; // เพิ่มอักขระนี้ในข้อมูลที่จะส่ง
// หากอักขระไม่ใช่แท็กปิด ให้กลับไปที่จุดเริ่มต้นของลูปและเพิ่มอักขระอื่นลงในข้อมูล ไปเรื่อยๆ จนกว่าจะพบแท็กปิดท้าย
if($simvol != ">" ) ( ดำเนินการต่อ;)
// หากพบแท็กปิด ตอนนี้เราจะส่งข้อมูลที่รวบรวมนี้ไปประมวลผล
// ตรวจสอบว่านี่เป็นรายการแรกในไฟล์หรือไม่ จากนั้นเราจะลบทุกอย่างที่อยู่หน้าแท็ก
// เนื่องจากบางครั้งคุณอาจพบขยะก่อนที่จะเริ่ม XML (ตัวแก้ไขที่งุ่มง่ามหรือสคริปต์ได้รับไฟล์จากเซิร์ฟเวอร์อื่น)
if($perviy_vxod ) ( $data = strstr ($data , ""
);
$perviy_vxod
=
0
;}
// ตอนนี้โยนข้อมูลลงในตัวแยกวิเคราะห์ xml
ถ้า (! xml_parse ($xml_parser, $data, feof ($fp))) (
// ที่นี่คุณสามารถประมวลผลและรับข้อผิดพลาดด้านความถูกต้องได้...
// ทันทีที่พบข้อผิดพลาด การแยกวิเคราะห์จะหยุดลง
เสียงสะท้อน "
ข้อผิดพลาด XML: " . xml_error_string(xml_get_error_code($xml_parser));
echo "ที่บรรทัด" . xml_get_current_line_number ($xml_parser);
หยุดพัก;
}
// หลังจากแยกวิเคราะห์แล้ว ให้ละทิ้งข้อมูลที่รวบรวมไว้สำหรับขั้นตอนถัดไปของวงจร
$ข้อมูล = "" ;
}
fclose($fp);
xml_parser_free($xml_parser);
// ลบตัวแปรโกลบอล
unset($GLOBALS [ "webi_deep" ]);
unset($GLOBALS [ "webi_tag_open" ]);
unset($GLOBALS [ "webi_data_temp" ]);
Webi_xml("1.xml");
?>
ตัวอย่างทั้งหมดมาพร้อมกับความคิดเห็น ตอนนี้ทดสอบและทดลองแล้ว
โปรดทราบว่าในฟังก์ชั่นการทำงานกับข้อมูล ข้อมูลไม่ได้ถูกแทรกลงในอาร์เรย์เพียงอย่างเดียว แต่จะถูกเพิ่มโดยใช้ " .="
เนื่องจากข้อมูลอาจไม่มาถึงทั้งหมด และหากคุณเพียงทำการมอบหมายงาน คุณจะได้รับข้อมูลเป็นชิ้นเป็นครั้งคราว
เพียงเท่านี้ตอนนี้ก็มีหน่วยความจำเพียงพอสำหรับการประมวลผลไฟล์ทุกขนาด แต่เวลาทำงานของสคริปต์สามารถเพิ่มขึ้นได้หลายวิธี
แทรกฟังก์ชันที่จุดเริ่มต้นของสคริปต์
set_time_limit (6000);
หรือ
ini_set ("max_execution_time" , "6000" );
หรือเพิ่มข้อความลงในไฟล์ .htaccess
php_value สูงสุด_execution_time 6000
ตัวอย่างเหล่านี้จะเพิ่มเวลาการทำงานของสคริปต์เป็น 6000 วินาที
คุณสามารถเพิ่มเวลาได้ด้วยวิธีนี้เฉพาะเมื่อปิดเซฟโหมดเท่านั้น
หากคุณมีสิทธิ์เข้าถึงการแก้ไข php.ini คุณสามารถเพิ่มเวลาได้
สูงสุด_execution_time = 6000
ตัวอย่างเช่น บนโฮสติ้ง Masterhost ในขณะที่เขียนบทความนี้ แม้จะห้ามการเพิ่มเวลาสคริปต์ก็ตาม เซฟโหมดแต่ถ้าคุณเป็นมืออาชีพ คุณสามารถสร้าง php build ของคุณเองบน masterhost ได้ แต่นั่นไม่ได้อยู่ในบทความนี้