ดึง XML มาแสดงผลยังไงครับ

เริ่มโพสต์โดย iannnnn, 03 ก.ค. 2006, 00:01 น.

0 สมาชิก และ 1 บุคคลทั่วไป กำลังเปิดอ่านโพสต์นี้

iannnnn


จักรี

ขอบคุณด้วยคนครับ   ตอนนี้ งานช้างของผมเลยละไอ้ xml เนี่ย   :39:
ล้ำลึกคนึงหาในดวงจิต ใจเคยคิดตัดสวาทมิอาจสิ้น
ดั่งก้านบัวหักกลางชลาสินธุ์ ผิว่าสิ้นไร้เยื่อยังเหลือใย

ยุนเอ

เราจะต้องการอะไรมากมายไปกว่า อะไรมากมาย

aodTo

#48
ผมพอจะมีตัวอย่างงานพวก Flash + XML บ้างครับ
ลองดูแล้วกัน
เป็นการทำระบบ Login โดยใช้ Flash + XML + ShareedObject
ไม่มีไรทำ ก็เลยลองทำเก็บไว้ตั้งนานแหละ  :42:



http://kmutt-it-wannapong.orgfree.com/portforio/register_class_complete.swf

ดาวน์โหลดไฟล์ตัวอย่าง : http://kmutt-it-wannapong.orgfree.com/portforio/SharedObject_XML.zip




/*
ลาก Label Component มาไว้ใน Libraly
ลาก TextInput Component มาไว้ใน Libraly
ลาก Button Component มาไว้ใน Libraly
ลาก DataGrid Component มาไว้ใน Libraly
*/

import mx.controls.Label;//import เข้ามาเพื่อใช้ในการสร้าง Label Component
import mx.controls.TextInput;//import เข้ามาเพื่อใช้ในการสร้าง TextInput Component
import mx.controls.Button;//import เข้ามาเพื่อใช้ในการสร้าง Button Component
import mx.controls.DataGrid;//import เข้ามาเพื่อใช้ในการสร้าง DataGrid Component
import mx.controls.gridclasses.DataGridColumn;//import เข้ามาเพื่อใช้ในการสร้างส่วนหัวของ DataGrid Component


//---------------------------------------------------------------------
startInput_x=250;//กำหนดตำแหน่งเริ่มต้นในแนวแกน    x ของ Object ที่วางบน   Stage
startInput_y=50;//กำหนดตำแหน่งเริ่มต้นในแนวแกน    y ของ Object ที่วางบน   Stage
depth=0;//กำหนดลำดับชั้นของ Object ที่วางบน   Stage
//----------------------------------------------------------------------
// สร้างข้อความขึ้นมา  ชื่อ user_label โดยมีค่าเท่ากับ Username :
createClassObject(Label,"user_label",depth++);
user_label.text="Username : ";
user_label.setSize(200,22);
user_label.move(startInput_x-100,startInput_y);
// สร้างช่องกรอกข้อความขึ้นมา  ชื่อ user_login
createClassObject(TextInput,"user_login",depth++);
user_login.setSize(200,22);
user_login.move(startInput_x,startInput_y);
//-----------------------------------------------------------------------
// สร้างข้อความขึ้นมา  ชื่อ pwd_label โดยมีค่าเท่ากับ Password :
createClassObject(Label,"pwd_label",depth++);
pwd_label.text="Password : ";
pwd_label.setSize(200,22);
pwd_label.move(user_label._x,user_label._y+user_label._height+2);
// สร้างช่องกรอกข้อความขึ้นมา  ชื่อ pwd_login
createClassObject(TextInput,"pwd_login",depth++,{password:true});
pwd_login.setSize(200,22);
pwd_login.move(startInput_x,user_login._y+user_login._height+2);
//-----------------------------------------------------------------------
// สร้างข้อความขึ้นมา  ชื่อ repwd_label โดยมีค่าเท่ากับ RePassword :
createClassObject(Label,"repwd_label",depth++);
repwd_label.text="RePassword : ";
repwd_label.setSize(200,22);
repwd_label.move(pwd_label._x,pwd_label._y+pwd_label._height+2);
// สร้างช่องกรอกข้อความขึ้นมา  ชื่อ repwd_login
createClassObject(TextInput,"repwd_login",depth++,{password:true});
repwd_login.setSize(200,22);
repwd_login.move(startInput_x,pwd_login._y+pwd_login._height+2);
//-----------------------------------------------------------------------
// สร้างปุ่มเอาไว้กดเพื่อสมัครสมาชิก ชื่อ btn_submit โดยมีข้อคามบนปุ่มว่า Submit
createClassObject(Button,"btn_submit",depth++,{label:"Submit"});
btn_submit.setSize(100,22);
btn_submit.move(startInput_x,repwd_label._y+repwd_label._height+5);
// สร้างปุ่มเอาไว้กดเพื่อ Clear ค่าที่กรอก  ที่ช่องกรอกข้อความ  ชื่อ btn_cancel โดยมีข้อคามบนปุ่มว่า Cancel
createClassObject(Button,"btn_cancel",depth++,{label:"Cancel"});
btn_cancel.setSize(100,22);
btn_cancel.move(startInput_x+btn_submit._width+5,repwd_label._y+repwd_label._height+5);
//---------------------------------------------------------------------------------------------------








//---------------------------------------------------------------------------------------------------
// สร้างข้อความขึ้นมา  ชื่อ listuser_label โดยมีค่าเท่ากับ --- มีสมาชิกทั้งหมด ---
createClassObject(Label,"listuser_label",depth++);
listuser_label.text="--- มีสมาชิกทั้งหมด ---";
listuser_label.setSize(200,22);
listuser_label.move(startInput_x+50,btn_submit._y+btn_submit._height+20);

//เป็นการสร้าง DataGrid Component ขึ้นมาชื่อ my_dg
createClassObject(DataGrid,"my_dg",depth++,{sortableColumns:false});
my_dg.setSize(400, 200);
my_dg.move(repwd_label._x,listuser_label._y+listuser_label._height+5);

/* เำพิ่มชื่อคอลัมเข้า Component DataGrid
- สร้าง Object  ชื่อ  user_dgc และกำหนดให้เวลาเราอ้างอิงตอนแพิ่มข้อมูลเข้า COlumn ชื่อว่า username_dgc
- กำหนดความกว้าง เท่ากับ 200
- ที่หัวของ Column แสดงข้อความว่า  Username
- เพิ่ม Column ที่สร้างขึ้นและกำหนดค่าต่างๆไว้เข้า Component DataGrid ชื่อ my_dg
*/
var user_dgc:DataGridColumn = new DataGridColumn("username_dgc");
user_dgc.width = 200;
user_dgc.headerText = "Username";
my_dg.addColumn(user_dgc);

/* เำพิ่มชื่อคอลัมเข้า Component DataGrid
- สร้าง Object  ชื่อ  pwd_dgc และกำหนดให้เวลาเราอ้างอิงตอนแพิ่มข้อมูลเข้า COlumn ชื่อว่า password_dgc
- กำหนดความกว้าง เท่ากับ 200
- ที่หัวของ Column แสดงข้อความว่า  Password
- เพิ่ม Column ที่สร้างขึ้นและกำหนดค่าต่างๆไว้เข้า Component DataGrid ชื่อ my_dg
*/
var pwd_dgc:DataGridColumn = new DataGridColumn("password_dgc");
pwd_dgc.width = 200;
pwd_dgc.headerText = "Password";
my_dg.addColumn(pwd_dgc);
//----------------------------------------------------------------------------------

/* สร้างปุ่มเอาไว้ลบชื่อที่เราเลือกชื่อที่อยู่บน Component DataGrid
- สร้างปุ่มชื่อ btn_delUser มีข้อความบนปุ่มว่า DeleteUser
- กำหนดความกว้าง เท่ากับ 400 สูง   200
- กำหนดตำแหน่ง x เท่ากับค่า startInput_x ซึ่งมีค่าเท่ากับ 250 ลบด้วย 100
    และตำแหน่ง y เืท่ากับตำแหน่ง y ของ Component DataGrid บวกด้วกความสูงของ Component DataGrid บวกด้วย 5
*/
createClassObject(Button,"btn_delUser",depth++,{label:"DeleteUser"});
btn_delUser.setSize(400,22);
btn_delUser.move(startInput_x-100,my_dg._y+my_dg._height+5);
//----------------------------------------------------------------------------------









//----------------------------------------------------------------------------------
//Listener Other........
//----------------------------------------------------------------------------------
//button submit
function listener_submit(){
if(user_login.text==""){
Selection.setFocus("user_login");
}else if(pwd_login.text==""){
Selection.setFocus("pwd_login");
}else if(repwd_login.text==""){
Selection.setFocus("repwd_login");
}else if(pwd_login.text!=repwd_login.text){
pwd_login.text="";
repwd_login.text="";
Selection.setFocus("pwd_login");
}else{
newUser();
}
}
btn_submit.addEventListener("click",listener_submit);

//button cancel
function listener_cancel(){
user_login.text="";
pwd_login.text="";
repwd_login.text="";
Selection.setFocus("user_login");
}
btn_cancel.addEventListener("click",listener_cancel);

//button delUser
function listener_delUser(){
delUser(my_dg.selectedIndex);
}
btn_delUser.addEventListener("click",listener_delUser);

//Label user_login
function listener_Label_userLogin(){
if(user_login.text=="มีผู้ใช้งานชื่อนี้แล้ว กรุณาใช้ชื่อใหม่"){
user_login.text="";
}
}
user_login.addEventListener("focusIn",listener_Label_userLogin);
//-------------------------------------------------------------------------------------






//---------------------------------------------------------------------------------------
// สร้าง Object และทำการค้นหาไฟล์ SharedObject ชื่อ  register_xml และดึงค่ามาเก็บไว้ใน Object so
// แต่ถ้าทำการค้นหาไฟล์ SharedObject ชื่อ  register_xml ไม่เจอก็จะสร้างไฟล์ SharedObject ชื่อ  register_xml.sol ขึ้นมาใหม่
so=SharedObject.getLocal("register_xml","/");

//ถ้า so.data.register_xml เท่ากับ undefined แสดงว่ายังไม่มีการสร้างตัวแปรตัวนี้
if(so.data.register_xml==undefined){
// สร้าง Object register_xml เป็นแบบ XML
so.data.register_xml=new XML();

// สร้าง Node ของ XML ขึ้นมา 4 Node โดยใช้ Method createElement()
var rootNode = so.data.register_xml.createElement("system");
childNode = so.data.register_xml.createElement("register");
username = so.data.register_xml.createElement("username");
pwd = so.data.register_xml.createElement("password");

// เพิ่ม  Node ที่สร้างขึ้นมาใหม่  เข้า  Object register_xml
so.data.register_xml.appendChild(rootNode);
rootNode.appendChild(childNode);
childNode.appendChild(username);
childNode.appendChild(pwd);

// สร้าง text Node ของ Node ต่างๆที่สร้างขึ้นโดยใช้ Method createTextNode()
var username_value:XMLNode = so.data.register_xml.createTextNode("admin");
var pwd_value:XMLNode = so.data.register_xml.createTextNode("1234");

// เพิ่ม Text Node เข้า  XML Node
username.appendChild(username_value);
pwd.appendChild(pwd_value);

// สั่งลให้ Save ข้อมูลต่างๆ เข้า SharedObject โดยใช้ Method flush()
so.data.flush();

}

//---------------------------------------------------------------------------------------------------------------------










//--------------------------------------------------------------------------------------------------------
function showUser(){
my_dg.removeAll();
for(i=0;i<so.data.register_xml.firstChild.childNodes.length;i++){
my_dg.addItem({username_dgc:so.data.register_xml.firstChild.childNodes[i].childNodes[0].firstChild.nodeValue,password_dgc:so.data.register_xml.firstChild.childNodes[i].childNodes[1].firstChild.nodeValue,data:so.data.register_xml.firstChild.childNodes[i].childNodes[0].firstChild.nodeValue});
}
}
showUser();

function newUser(){
checkUser=false;
// วนเช็คว่ามีชื่ออยู่แล้วหรือไม่  ถ้ามีก็จะทำให้ checkUser มีค่าเท่ากับ true และออกจากการทำงานของ Loop For
for(i=0;i<so.data.register_xml.firstChild.childNodes.length;i++){
if(user_login.text==so.data.register_xml.firstChild.childNodes[i].childNodes[0].firstChild.nodeValue){
checkUser=true;
break;
}
}

if(checkUser==false){
// สร้างตัวแปรเก็บค่าของ NodeElement สุดท้ายเพื่อเอาไว้อ้างอิงเราเพิ่ม Node เข้า XML Method insertBefore()
var insertPoint:XMLNode = so.data.register_xml.firstChild.childNodes.lastChild;

// สร้าง Node ของ XML ขึ้นมา 3 Node โดยใช้ Method createElement()
new_childNode = so.data.register_xml.createElement("register");
new_username = so.data.register_xml.createElement("username");
new_pwd = so.data.register_xml.createElement("password");

// เพิ่ม  Node ที่สร้างขึ้นมาใหม่  เข้า  rootNode ซึ่งก็คือต่อจาก Node <system>...</system>
rootNode.appendChild(new_childNode);
new_childNode.appendChild(new_username);
new_childNode.appendChild(new_pwd);

// สร้าง text Node ของ Node ต่างๆที่สร้างขึ้นโดยใช้ Method createTextNode()
new_username_value = so.data.register_xml.createTextNode(user_login.text);
new_pwd_value = so.data.register_xml.createTextNode(pwd_login.text);

// เพิ่ม Text Node เข้า  XML Node
new_username.appendChild(new_username_value);
new_pwd.appendChild(new_pwd_value);

// เป็นก็เพิ่ม Node ที่เราสร้างขึ้นใหม่ ชื่อ new_childNode และจะอ้างอิงตำแหน่งการเพิ่มเข้าไปด้วยก็คือตัวแปร insertPoint
so.data.register_xml.firstChild.insertBefore(new_childNode, insertPoint);
// ตรงนี้สำคัญมาก   เพราะบางคนอาจจะงง  ว่าทำไมถึงเพิ่ม Node หลายขั้นตอนจัง ทั้งใช้ appendChild() insertBefore()
/*  ซึ่งก็น่าจะพอแล้ว  ทั้งๆที่เราก็ใช้  Path --> so.data.register_xml.firstChild.insertBefore()
  เราลอง Command บรรทัดนี้ดู     so.data.register_xml=new XML(so.data.register_xml);
ซึ่งก็เป็นการเพิ่มชื่อได้เหมือนกัน  แต่เวลาเราปิด Movie และกลับมาเิ่ล่น Movie ใหม่กลับไม่มีชื่อที่เราเพิ่ม 
ซึ่งเหตุการณ์นี้เป็น เพราะมันไม่ถูกเขียนเข้า SharedObject เหมือนการใช้ Array

ผมก็เลยแก้ปัญหาโดยการสร้าง XML ขึ้นใหม่เลยแต่เอาค่าเดิม  ซึ่งดูเหมือนซ้ำซ้อน  ผมก็ไม่รู้จะใช้วิธีไหนเหมือนกันใครเก่งเรื่อง XML ก็ช่วยเขียน
Code หน่อยแล้วกันครับ  เพราะผมทำเรื่องนี้  เปิด Help ทำด้วยซ้ำในส่วนของ XML  อิอิ......
*/
so.data.register_xml=new XML(so.data.register_xml);

// สั่งให้ Save ข้อมูลต่างๆ เข้า SharedObject โดยใช้ Method flush()
so.data.flush();
// เรียก Function showUser() เพื่อ  Update ค่าที่แสดงบน Component DataGrid ใหม่
showUser();

// ถ้า checkUser เท่ากับ true แสดงว่า ชื่อที่กรอก มีคนใช้แล้ว
}else if(checkUser==true){
user_login.text="มีผู้ใช้งานชื่อนี้แล้ว กรุณาใช้ชื่อใหม่";
}

}
// สร้าง Function เพื่อลบสมาชิกออกจากระบบ
function delUser(index){
cityNode = so.data.register_xml.firstChild.childNodes[index];
cityNode.removeNode();
so.data.register_xml=new XML(so.data.register_xml);
so.data.flush();
showUser();
}
//----------------------------------------------------------------------------------------


จบงับ  :26:

จักรี

โอ้ว ขอบคุณครับ   ผมก็เคยตกอยุ๋ในวังวนของแชร์ออปเจ๊กอยุ๋พักนึงเหมือนกัน   :41:



อ้าวเฮ้ย  นี่อ๊อดใช่มั้ยเนี่ย..............

ล้ำลึกคนึงหาในดวงจิต ใจเคยคิดตัดสวาทมิอาจสิ้น
ดั่งก้านบัวหักกลางชลาสินธุ์ ผิว่าสิ้นไร้เยื่อยังเหลือใย

aodTo

อิอิ รู้ได้ไง :43:
คงเป็น Kree ใช่ไหม เจอเพื่อนเก่า อิอิ  :26:

iannnnn


แอ๊ะ

โอ้วววว ความรู้เพียบ ขอบคุณครับ  :45:
[ว่างให้เช่า]

X Saint

คล้ายๆ ตัวเดิมที่เคยทำเมื่อนานมาแล้วครับ (นานมาก ไฟล์หายไปแล้ว -__-')
ปรับปรุงนิดหน่อย ตัวนี้จะใส่ url ของ RSS ที่ต้องการแสดงใน Flash แล้วกดปุ่มให้มันดึงมาแสดงผลได้เลย

ยังคงแสดงผล 3 ข้อมูลแรกเหมือนเดิม และตัวนี้ไม่มี scroll bar เหมือนเดิมครับ ถ้าไป feed เว็บไหนที่ข้อมูลยาวๆ เช่น iannnnn.com มันก็จะยืดยาว จนมองไม่เห็นข้างล่าง (ถ้าคลิกเมาส์ลากๆ ลงจะเห็น)

http://www.x-sense.com/project/rssReader.swf

X Saint

ตัวนี้ทำให้อ่านเฉพาะ RSS นะครับ ไม่อ่าน atom
ก่อนที่จะไปสู่รายละเอียดบน Flash และ ActionScript
มาวิเคราะห์ข้อมูลที่จะดึงมาก่อน ในที่นี้คือ xml ที่อยู่ในรูปแบบ RSS


X Saint

โครงสร้างของ RSS ในทุกๆ เว็บจะมีโครงสร้างในลักษณะภาพด้านบนครับ (สมมุติว่าเราจะทำให้อ่าน RSS 2.0 อย่างเดียวนะครับ)

สิ่งที่เราต้องการมาแสดงผลในที่นี้คือ title, pubDate, link, description ของข้อมูล 3 อันล่าสุด
ซึ่งข้อมูลทั้ง 4 นี้จะอยู่ใน Element item

อันดับแรกทำความเข้าใจกับโครงสร้าง RSS ก่อนครับ (ดูรายละเอียดเพิ่มเติมได้ที่ http://cyber.law.harvard.edu/rss/rss.html)

RSS จะมี root node คือ <rss>

ภายใน node นี้จะมี <channel>

ภายใน channel ก็จะมี tag อีกมากมาย เช่น title ของ RSS ตัวนี้ category, description, etc. รวมทั้ง <item> ที่เราต้องการดึงข้อมูลมาใช้ด้วย

ดังนั้นจะเห็นว่าข้อมูลที่เราต้องการดึงมาใช้นั้นจะอยู่ในลำดับขั้นนี้ (hierachy) การวิเคราะห์โครงสร้างของ xml ที่ต้องการใช้ จะมีผลต่อการเขียน ActionScript ให้ดึงข้อมูลออกมา ซึ่งตอนนี้เราก็รู้แล้วว่ามันอยู่ในลำดับไหน มีความสัมพันธ์เช่นไรกับ root node

ในส่วนต่อไป ก็จะเริ่มทำความเข้าใจกับการอ่าน XML ด้วย ActionScript ครับ

X Saint

#56
บน Stage มี Dynamic Text 1 ตัว ชื่อ dispTxt สำหรับแสดงผลลัพธ์นะครับ
แล้วด้านล่างเป็น Input Text ชื่อ urlTxt สำหรับใส่ url
ส่วนปุ่ม GO นั่นชื่อว่า btnGO ครับ

มาดูส่วน code ครับ เพื่อไม่ให้ยืดยาวผมเอา code มาแปะเลยละกันครับ
เอาเป็นแบบว่า ถ้าใครสงสัยส่วนไหนก็เขียนมานะครับ ผมจะได้อธิบายส่วนนั้นอีกที
จะได้รู้ว่าส่วนไหนที่คนสงสัยครับ

var xmlDoc:XML = new XML();
var url:String = "http://rss.gamespot.com/misc/rss/gamespot_updates_news.xml";
xmlDoc.load("proxyCrossDomain.php?url="+url);
xmlDoc.ignoreWhite = true;


ส่วนแรกผมตั้งตัวแปร url เพื่อเป็น default ให้ไปอ่านหัวข้อข่าวล่าสุดจากเว็บ gamespot.com ครับ
แล้วให้ xmlDoc โหลด RSS นั้นผ่าน proxy script (เพราะเป็นการโหลดค่าข้ามโดเมน - ถ้าสงสัยส่วนนี้บอกได้ครับ) คือตัว proxyCrossDomain.php ครับ

X Saint

#57
ส่วนต่อมาเป็นฟังก์ชั่นที่มารับจาก event onLoad ของ xmlDoc ครับ

xmlDoc.onLoad = function(success:Boolean):Void  {
if (success) {
urlTxt.htmlText = url;
dispTxt.text = "";
dispFeed(this.firstChild);
} else {
dispTxt.text = "Can not load xml data";
}
};


ส่วนต่อมาเป็นฟังก์ชั่นค้นหาโหนดที่ต้องการครับ

function getNodeText(inNode:XMLNode, tagName:String):String {
if (inNode.nodeName == tagName) {
return inNode.firstChild.toString();
} else if (inNode.nextSibling != null) {
return getNodeText(inNode.nextSibling, tagName);
}
}


ถัดมาเป็นฟังก์ชั่นสำหรับแสดงผล ซึ่งถูกเรียกใช้จากอีเวนต์ onLoad ของ xmlDoc ครับ

function dispFeed(xmlFeed:XMLNode):Void {
var xmlChannel:XMLNode = xmlFeed.firstChild;
var aItem:Array = xmlChannel.childNodes;
var itemCnt:Number = 0;
var itemMax:Number = 3;

for (var i:Number = 0; i<aItem.length; i++) {
if (aItem[i].nodeName == "item") {
var vPubDate:String = getNodeText(aItem[i].firstChild, "pubDate");
var vTitle:String = getNodeText(aItem[i].firstChild, "title");
var vLink:String = getNodeText(aItem[i].firstChild, "link");
var vDesc:String = getNodeText(aItem[i].firstChild, "description");
dispTxt.htmlText += "<b><a href=\""+vLink+"\" target=\"_blank\">"+vTitle+"</a></b>\n";
dispTxt.htmlText += vPubDate+"\n"+vDesc+"\n\n";
itemCnt++;
if (itemCnt == itemMax) break;
}
}
}


ส่วนสุดท้ายจะเป็นปุ่ม GO นะครับ

X Saint

ส่วนสุดท้ายสำหรับให้ปุ่ม GO ทำการ update ข้อมูลจาก url ที่ระบุครับ

btnGO.onRelease = function():Void {
url=urlTxt.text;
xmlDoc.load("proxyCrossDomain.php?url="+url);
}


เสร็จแล้วครับ feed reader แบบง่ายๆ บน Flash พอจะสรุปแบ่งเป็นหัวข้อย่อยได้ดังนี้ครับ
1. การอ่าน XML ด้วย XML และ XMLNode
2. การอ่านข้อมูลข้ามโดเมน
3. การดึงค่าจาก RSS หรือ xml
4. หลักการของฟังก์ชั่น getNodeText
5. หลักการของฟังก์ชั่น dispFeed

สงสัยหัวข้อไหนก็ระบุมานะครับ

WuTtY

อ้างคำพูดจาก: X Saint เมื่อ 30 ก.ค. 2007, 09:55 น.
ส่วนแรกผมตั้งตัวแปร url เพื่อเป็น default ให้ไปอ่านหัวข้อข่าวล่าสุดจากเว็บ gamespot.com ครับ
แล้วให้ xmlDoc โหลด RSS นั้นผ่าน proxy script (เพราะเป็นการโหลดค่าข้ามโดเมน - ถ้าสงสัยส่วนนี้บอกได้ครับ) คือตัว proxyCrossDomain.php ครับ

ถามนิดนึงเรือ่ง cross domain ครับ
1. flash มันจะไม่ยอมให้ไปอ่าน rss อื่นตรง ๆ เหรอครับ ทำไมต้องใช้ proxy script ด้วย
2. proxy script นี่ทำอะไรบ้างครับ ไป get rss xml แล้ว return ออกมาตรง ๆ ใช่หรือเปล่า ?

SMF 2.1.7 © 2026, Simple Machines