ดูตัวอย่าง Code ก่อนละกัน แล้วค่อยเป็นค่อยไปนะครับ
<?php
/******* นี้เป็นตัวอย่างเอกสารที่เป็น xml นะครับ ********/
$xml_string = "
"<?xml version='1.0'?>
<Order>
<BuyerID>1</BuyerID>
<Staff>
<StaffID>12</StaffID>
<StaffName>aadfor</StaffName>
</Staff>
<DueDate>12-30-23</DueDate>
<OrderList>
<OrderItem>
<ItemID>1</ItemID>
<Amount>20</Amount>
</OrderItem>
<OrderItem>
<ItemID>2</ItemID>
<Amount>30</Amount>
</OrderItem>
<OrderItem>
<ItemID>3</ItemID>
<Amount>40</Amount>
</OrderItem>
<OrderItem>
<ItemID>4</ItemID>
<Amount>50</Amount>
</OrderItem>
</OrderList>
</Order>";
/**********ตัวโปรแกรมเริ่มตรงนี้ละกัน **********/
// อ่านเอกสาร ที่เป็น xml และทำการตรวจสอบ
if(!$doc = xmldoc($xml_string))
die("Error passing XML");
// กำหนดตัวแปร Root เริ่มต้นอ่านเอกสาร
$root = $doc->root();
// ลงไปลึก 1 ระดับเพื่อจะอ่านข้อมูล Element ของลูก ๆ
$children = $root->children();
// ตัวแปร $children จะเป็น อาร์เรย์ ดังนั้นจึงสามารถใช้ foreach ท่องไปยังแต่ละ element ภายในเอกสารได้ ในที่นี้ให้ตัวแปร $child เก็บ element ค่า element ที่กำลังท่องอยู่
foreach($children as $child)
{
// ต้องทำการตรวจสอบ type ของ element ว่าเป็น XML_ELEMENT_NODE รึเปล่า รายละเอียดค่อยกล่าวเพิ่มเติมในท้ายเอกสาร ซึ่งในที่นี้เราจะสนใจเฉพาะ element ชนิดนี้ก่อน
if ($child->type == XML_ELEMENT_NODE)
{
//ตรวจสอบป้ายของ element ว่ามีป้ายเป็นอะไรโดยใช้ property tagname ในการตรวจสอบ
switch($child->tagname) {
//ในกรณีป้ายเป็น BuyerID
case "BuyerID":
// ใน BuyerID นั้นไม่มี element อื่น ๆ ภายใน (ตัวมันเองเก็บ Content) ดังนั้นเราจึงสามารถดึง Content มาได้เลย ซึ่งจะต้องรับค่ามาจาก childrent อีกที วิธีการดึงให้ดูจาก code ละกัน
$text = $child->children();
$BuyerID = $text[0]->content;
echo $child->tagname." = ".$BuyerID."<br>";
break;
//ในกรณีป้ายเป็น Staff
case "Staff":
//ป้ายนี้จะมีลูกอยู่ภายในอีก 1 ชั้น ดังนั้นเราจึงต้องเข้าไปอีก 1 ชั้นโดยใช้คำสั่ง children อีกครั้ง
$staffNode = $child->children();
//เหมือนกับข้างต้นที่กล่าวมาแล้วคือ element ที่ได้นั้นจะเป็นอาร์เรย์ดังนั้นเราจึงสามารใช้ foreach เพื่อจะเข้าถึง element แต่ละตัวภายใน node นี้ ในที่นี้เราใช้ตัวแปร $staffElement element ที่กำลังท่องอยู่ในขณะนั้น
foreach($staffNode as $staffElement) {
//ตรวจสอบชนิดที่เป็น XML_ELEMENT_NODE
if ($staffElement->type == XML_ELEMENT_NODE) {
//ตรวจสอบป้ายของ element และเก็บค่าเข้าตัวแปรพร้อมพิมพ์ (ขอไม่อธิบายรายละเอียด เนื่องจากเหมือนข้างบน)
if($staffElement->tagname == "StaffID") {
$text = $staffElement->children();
$staffID = $text[0]->content;
echo $staffElement->tagname." = ".$staffID."<br>";
} else
if($staffElement->tagname == "StaffName") {
$text = $staffElement->children();
$staffName = $text[0]->content;
echo $staffElement->tagname." = ".$staffName."<br>";
}
//ในกรณีเจอป้ายที่ไม่ประกาศไว้แสดงว่าเอกสารผิดพลาด ก็เลยให้มันจบการทำงานเสีย
else die("ERROR:Invalid format!");
}
}
break;
// กรณีป้ายเป็น DueDate เหมือนกับป้าย BuyerID
case "DueDate":
$text = $child->children();
$DueDate = $text[0]->content;
echo $child->tagname." = ".$DueDate."<br>";
break;
// กรณีป้าย OrderList ป้ายนี้จะมีลูกอยู่ 2 ระดับชั้น คือ OrderItem คือชั้นที่ 1 และ ภายใน OrderItem ก็จะเป็นรายละเอียดคือ ItemID และ Amount เป็นชั้นที่สอง ซึ่งเราจะต้องเข้าไปทีละชั้นเพื่อที่จะเข้าไปกับข้อมูลมา ลองทำความเข้าใจเพิ่มเติมดูนะครับ (ถึงตรงนี้แล้วไม่น่าจะยาก)
case "OrderList":
$orderList = $child->children();
foreach ($orderList as $orderListElement) {
if ($orderListElement->type == XML_ELEMENT_NODE) {
if ($orderListElement->tagname == "OrderItem") {
$orderItem = $orderListElement->children();
foreach($orderItem as $orderItemElement) {
if ($orderItemElement->type == XML_ELEMENT_NODE) {
if ($orderItemElement->tagname == "ItemID") {
$text = $orderItemElement->children();
$itemID = $text[0]->content;
} else
if ($orderItemElement->tagname == "Amount") {
$text = $orderItemElement->children();
$amount[$itemID] = $text[0]->content;
}
else die("ERROR:Invalid format!");
}
}
echo "Item: ".$itemID." - ".$amount[$itemID]."<br>";
}
}
}
break;
default: die("ERROR:Invalid format!");
}
}
}
/**************************** End Read XML ********************************/
?>
เมื่อสั่งทำงานจะแสดงผลดังนี้
BuyerID = 1
StaffID = 12
StaffName = aadfor
DueDate = 12-30-23
Item: 1 - 20
Item: 2 - 30
Item: 3 - 40
Item: 4 - 50
ข้อมูลเพิ่มเติม
ชนิดของข้อมูลมีดังนี้ครับ
Integer |
Node type |
Description |
---|---|---|
1 |
XML_ELEMENT_NODE |
Element |
2 |
XML_ATTRIBUTE_NODE |
Attribute |
3 |
XML_TEXT_NODE |
Text |
4 |
XML_CDATA_SECTION_NODE |
CDATA section |
5 |
XML_ENTITY_REF_NODE |
Entity reference |
7 |
XML_PI_NODE |
Processing instruction |
8 |
XML_COMMENT_NODE |
Comment |
9 |
XML_DOCUMENT_NODE |
XML document |
12 |
XML_NOTATION_NODE |
Notation |
รายละเอียด เอาเท่าที่รู้ตอนนี้นะครับ
element 1-3 ก็มีความหมายตามตัวเลยครับ ซึ่งได้แก่ element attribute และ text แต่มีข้อสังเกตเพิ่มเติม โดยให้ลองทดสอบ code ต่อไปนี้
<?php
$xml_string = "
<root>
text_root1
<child1>text_child1</child1>
text_root2
<child2 attr='text_child_attribute'>text_child2</child2>
text_root3
</root>";
if(!$doc = xmldoc($xml_string))
die("Error passing XML");
$root = $doc->root();
$children = $root->children();
foreach($children as $child)
{
switch($child->type){
case XML_ELEMENT_NODE:
$text = $child->children();
echo "XML_ELEMENT_NODE:".$child->tagname." CONTENT:".$text[0]->content."<br>";
if ($child->get_attribute("attr"))
echo " ATTRIBUTE:".$child->get_attribute("attr")."<br>";
break;
case XML_TEXT_NODE:
echo "XML_TEXT_NODE:".$child->content."<br>";
break;
default:
echo "ORTHER ELEMENT:";
print_r($child);
echo "<br>";
}
}
?>
ผลการทำงานที่ได้
XML_TEXT_NODE: text_root1
XML_ELEMENT_NODE:child1 CONTENT:text_child1
XML_TEXT_NODE: text_root2
XML_ELEMENT_NODE:child2 CONTENT:text_child2
ATTRIBUTE:text_child_attribute
XML_TEXT_NODE: text_root3
จากผลการทำงานจะเห็นได้ว่า ทุกๆ ครั้งที่เราเข้าไปใน element นั้นจะมี element ชนิด XML_TEXT_NODE คั้นระหว่างแต่ละ element แม้ว่าในเอกสาร xml ที่เราดำเนินการด้วยนั้นจะไม่มี element นั้นก็จะมี content เป็น string ว่างแทน
ไม่มีความเห็น