装配与改变XML对象
出可以对XML元素与对象赋值外,你也可以通过使用E4X组装与传递XML对象。
下边的例子中,你可以使用prependChild()和append()方法来向XML对象的列表中的前边或后边增减一个属性。类似的,使用insertChildBefore()方法和insertchildAfter()方法来增加属性在指定的属性之前或之后。要删除元素,使用delete()方法从XML中移除节点。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
width="500" height="600"
creationComplete="myDataGrid.selectedIndex=0; validateForm();">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
// Constants
private const SELECTED_ITEM:uint = 0;
private const THE_LIST:uint = 1;
private const BEFORE:uint = 0;
private const AFTER:uint = 1;
// Flag: is the form valid?
[Bindable]
private var formIsValid:Boolean;
// Flag: does a selection exist in the data grid?
[Bindable]private var selectionExists:Boolean;
// Holds the index of the next item in the
// data grid following the deletion of a book item.
private var newSelectedIndex:int;
// Model: XML structure describing
// some of the books in my collection.
[Bindable]
private var myBooks:XML =
<books><book ISBN="1590595181">
<title>Foundation ActionScript Animation: Making Things Move</title>
<author>Keith Peters</author><amazonUrl>http://tinyurl.com/npuxt</amazonUrl>
</book>
<book ISBN="1582346194">
<title>Send in the Idiots: Stories from the Other Side of Autism</title><author>Kamran Nazeer</author>
<amazonUrl>http://tinyurl.com/lo5ts</amazonUrl>
</book></books>
// Add a new book.
private function addBookHandler():void
{// Create a new XML Object from the form information
var newBook:XML =
<book ISBN={isbnInput.text}>
<title>{titleInput.text}</title><author>{authorInput.text}</author>
<amazonUrl>{amazonUrlInput.text}</amazonUrl>
</book>;
// Save the selected book's index so it can be reselected// in the grid once the new book is added.
var selectedBookIndex:uint = myDataGrid.selectedIndex;
// Does the user want to add the new
// book relative to the selected book in the
// data grid or relative to the list itself?
if (addRelativeTo.selectedIndex == SELECTED_ITEM){
// Add the new item relative to the selected item.var selectedBook:XML = myBooks.book[selectedBookIndex];
// Does the user want to add it before or after// the selected item?
if (addPosition.selectedIndex == BEFORE)
{
// Add new item before selected item
myBooks = myBooks.insertChildBefore(selectedBook, newBook);
}else
{
// Add new item after selected item
myBooks = myBooks.insertChildAfter(selectedBook, newBook);
}}
else
{
// Add the new item relative to the whole list of books.
if (addPosition.selectedIndex == BEFORE){
// Add new item at the start of the list.
myBooks = myBooks.prependChild(newBook);
}
else{
// Add new item at the end of the list.
myBooks = myBooks.appendChild(newBook);
}
}// Select the previously selected item in the grid
// so the user doesn't lose their position. (If a new book was
// added before the currently selected item, that item's
// new index will be one greater, so select that.)
var newSelectedIndex:uint = (addPosition.selectedIndex == BEFORE) ? selectedBookIndex + 1: selectedBookIndex;
myDataGrid.selectedIndex = newSelectedIndex;
}
// Delete selected bookprivate function deleteBookHandler():void
{
// Save the currently selected index.
var selectedBookIndex:int = myDataGrid.selectedIndex;
// Delete the currently selected book.delete (myBooks.book[selectedBookIndex]);
// Reselect the next logical item in the data grid.
newSelectedIndex = (selectedBookIndex==0) ? 0 : selectedBookIndex - 1;// Change the selected index of the data grid
// at a later frame. See note on changeDataGridIndex()
// method for more details on this workaround.
callLater ( changeDataGridIndex );
}// This is a workaround for a known issue with
// List-based components where deleting an item
// from the control's dataProvider leaves the// selectedIndex at an incorrect value. The workaround
// is to reassign the data provider at least a
// frame later and to change the index there.
private function changeDataGridIndex ():void
{// Reassign the data grid's data provider.
myDataGrid.dataProvider = myBooks.book;// Set the selected index.
myDataGrid.selectedIndex = newSelectedIndex;// Validate the form to make sure that there
// is actually a selection (that the grid is
// not empty).validateForm();
}
// Perform simple form validation.
private function validateForm():void{
// Is the form valid?
formIsValid =
isbnInput.text != ""
&& titleInput.text != ""&& authorInput.text != ""
&& amazonUrlInput.text != "";
// Does a selection exist in the data grid?
selectionExists = myDataGrid.selectedIndex != -1;
}]]>
</mx:Script>
<!-- User interface -->
<mx:Panel
title="Assigning XML data"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"
><!-- List of books -->
<mx:DataGrid
id="myDataGrid"
dataProvider="{myBooks.book}"
change="validateForm();"
><mx:columns>
<mx:DataGridColumn dataField="@ISBN" headerText="ISBN" width="85"/>
<mx:DataGridColumn dataField="title" headerText="Title"/><mx:DataGridColumn dataField="author" headerText="Author"/>
<mx:DataGridColumn dataField="amazonUrl" headerText="Web site"><mx:itemRenderer>
<mx:Component>
<mx:LinkButton
label="Visit"
click="navigateToURL(new URLRequest(data.amazonUrl), 'blank');"
/>
</mx:Component></mx:itemRenderer>
</mx:DataGridColumn>
</mx:columns>
</mx:DataGrid>
<!-- New book form. Prepopulated with a book for easier testing. --><mx:Form width="100%" autoLayout="false">
<mx:FormHeading label="New book details"/><mx:FormItem label="ISBN:" width="
100%">
<mx:TextInput
id="isbnInput"
width="100%"
text="1590596196"
change="validateForm();"
/></mx:FormItem>
<mx:FormItem label="Title:" width="100%">
<mx:TextInput
id="titleInput"
width="100%"
text="Object Oriented Actionscript for Flash 8"
change="validateForm();"
/></mx:FormItem>
<mx:FormItem label="Author:" width="100%">
<mx:TextInput
id="authorInput"
width="100%"
text="Peter Elst"
change="validateForm();"
/></mx:FormItem>
<mx:FormItem label="Amazon Url" width="100%">
<mx:TextInput
id="amazonUrlInput"
width="100%"
text="http://tinyurl.com/qxon2"
change="validateForm();"
/></mx:FormItem>
</mx:Form>
<mx:TextArea id="deb" width="100%"/>
<mx:ControlBar><mx:Button
label="Add book"
click="addBookHandler();"
enabled="{formIsValid}"
/>
<mx:ComboBox id="addPosition" enabled="{formIsValid}"><mx:String>before</mx:String>
<mx:String>after</mx:String>
</mx:ComboBox>
<mx:ComboBox
id="addRelativeTo"
enabled="{formIsValid}"
><mx:String>selected item.</mx:String>
<mx:String>the list.</mx:String>
</mx:ComboBox>
<mx:VRule height="15"/><mx:Button
label="Delete book"
click="deleteBookHandler();"
enabled="{selectionExists}"
/>
</mx:ControlBar></mx:Panel>
</mx:Application>
查询XML数据
在E4X中,查询XML数据有几种方式。下边的例子展示了一下几种方式:
- 使用逻辑操作搜索数字范围(例如,所有大于300页的图书)
- 在元素或属性上查询字符串(例如,标题包含ldiots的图书)
- 从重复的节点请求元素(例如,从books中title元素)
当你拥有了查询结果,你可以使用for..in和 for each..in循环来遍历结果。
例子
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
viewSourceURL="src/XMLQuery/index.html"
width="450" height="290"
initialize="initializeHandler();"
><mx:Script>
<![CDATA[
// Model: XML structure describing
// some of the books in my collection.
[Bindable]private var myBooks:XML =
<books>
<book ISBN="1590595181"><title>Foundation ActionScript Animation: Making Things Move</title>
<author>Keith Peters</author>
<amazonUrl>http://tinyurl.com/npuxt</amazonUrl><pageCount>470</pageCount>
</book>
<book ISBN="1582346194">
<title>Send in the Idiots: Stories from the Other Side of Autism</title><author>Kamran Nazeer</author>
<amazonUrl>http://tinyurl.com/lo5ts</amazonUrl>
<pageCount>500</pageCount></book>
<book ISBN="1590592212">
<title>Flash 3D Cheats Most Wanted</title>
<author>Aral Balkan et. al.</author><amazonUrl>http://tinyurl.com/gsd7b</amazonUrl>
<pageCount>256</pageCount>
</book></books>
private function initializeHandler():void
{// Line length to truncate strings at when
// displaying them
var lineLength:uint = 50;
//
// Find books with more than 300 pages.
//var resultA:XMLList;
resultA = myBooks.book.(pageCount > 300);
// Display the found books using a for each..in
// loop.var tempString:String = "<ul>";
for each (var book:XML in resultA){
tempString += "<li>" + truncate(book.title, lineLength) + "</li>";
}tempString += "</ul>";
aText.htmlText = tempString;
//
// Find book with "Idiots" in the title.
//
var resultB:XMLList;
resultB = myBooks.book.(title.toString().search("Idiots")>-1);
// Display the title of the found book.bText.htmlText = "<ul><li>" + truncate(resultB.title, lineLength) + "</li></ul>";
//// Get the titles of all the books.
//
var resultC:XMLList;
resultC = myBooks.book..title;
// Display the titles using a for..in loop
tempString = "<ul>";
for (var bookTitle:String in resultC){
tempString += "<li>" + truncate(resultC[bookTitle], lineLength) + "</li>";
}tempString += "</ul>";
cText.htmlText = tempString;
}
// Helper method: Truncate a string at a given character count. Tries
// to do this intelligently by truncating at a space if one exists in// the string (so that words are not truncated in the middle).
private function truncate ( str:String, numChars:uint, symbol:String = "..." ):String
{// Don't do anything if the string is shorter than the maximum value.
if (str.length <= numChars) return str;
// Search backward for a space in the string, starting with
// the character position that was requested.var charPosition:uint = numChars-1;
while (str.charAt(charPosition) != " " && charPosition != 0){
charPosition--;
}
var truncateAt:uint = charPosition == 0 ? numChars : charPosition;
// If the space is right before a punctuation mark, crop the// punctuation mark also (or else it looks weird).
var charBefore:String = str.charAt(truncateAt-1);
if (charBefore == ":" || charBefore == ";"
|| charBefore == "." || charBefore == ","){
truncateAt--;
}
// Truncate the string.
var newString:String = str.substr(0, truncateAt);
newString += symbol;
// Return the truncated string.return newString;
}]]>
</mx:Script>
<!-- User interface --><mx:Panel
title="XML lookup results" width="100%"
paddingBottom="10" paddingLeft="10" paddingRight="10" paddingTop="10"><mx:Label text="Query A - Books found:" fontWeight="bold"/>
<mx:Text id="aText" width="100%"/><mx:Label text="Query B - Books found:" fontWeight="bold"/>
<mx:Text id="bText" width="100%"/><mx:Label text="Query C - Books found:" fontWeight="bold"/>
<mx:Text id="cText" width="100%"/></mx:Panel>
</mx:Application>