The XML examples represent a book in a library. However the book has several bookworms in it.
Using E4X we can find these bookworms.

 
<library>
	<book>
<page id="one"/>
		<worm name="Eddy" />
<page id="two"/>
<page id="three">
			<worm name="Lisa"/>
			<worm name="Pete" />
		</page>
<page id="four"/>
	</book>
</library>
 

There are some E4X operators and XML methods to help use do this when combined together:

.. Access all descendants of the XML object.
. Access a property of an Object or XML.
* Wildcard, match any part of the XML.
childIndex() Index number of an XML object relative to its parent node.
name() Name of the XML node.

Return a certain "worm" node at the index it belongs to from its XMLList.
Any nested "worm" node occurrence is also considered.

 
var doc:XML=
<library>
	<book>
<page id="one"/>
		<worm name="Eddy" />
<page id="two"/>
<page id="three">
			<worm name="Lisa"/>
			<worm name="Pete" />
		</page>
<page id="four"/>
	</book>
</library>;
 
//Pick the "worm" node at index 1.
var data:*=doc..*.worm[1];
trace(data.toXMLString());
 
/*=========================================
OUTPUT:
 
<worm name="Lisa"/>			//worm[1]
===========================================*/
 

Delete all "worm" nodes from the xml, even the nested ones.

 
var doc:XML=
<library>
	<book>
<page id="one"/>
		<worm name="Eddy" />
<page id="two"/>
<page id="three">
			<worm name="Lisa"/>
			<worm name="Pete" />
		</page>
<page id="four"/>
	</book>
</library>;
 
delete doc..*.worm;
trace(doc.toXMLString());
 
/*=========================================
OUTPUT:
All "worm" nodes are deleted.
<library>
  <book>
<page id="one"/>
<page id="two"/>
<page id="three"/>
<page id="four"/>
  </book>
</library>
===========================================*/
 


Use E4X filtering with Regular Expressions.

XML methods and Regular Expressions can be used inside parentheses to accomplish E4X filtering.

doc..*.(childIndex()==0 && /library|book/i.test(name())==false)

List all nodes that belong at a given index of their XMLList.

 
var doc:XML=
<library>
	<book>
<page id="one"/>
		<worm name="Eddy" />
<page id="two"/>
<page id="three">
			<worm name="Lisa"/>
			<worm name="Pete" />
		</page>
<page id="four"/>
	</book>
</library>;
 
//----------------------------------------------------
//Get the first node of each list whose name does not
//match the regular expression.
//----------------------------------------------------
var data:*=doc..*.(childIndex()==0 && /library|book/i.test(name())==false);
trace(data.toXMLString());
 
/*=========================================
OUTPUT:
<page id="one"/>
<worm name="Lisa"/>
===========================================*/
 
4 Responses to “Using E4X with XML in AS3”
  1. re: delete doc..*.worm;

    So if the worm nodes had another attribute – say type, with ‘good’ or ‘evil’, and say 2 were ‘evil’ – how would you filter the xml to delete just the evil 2?

    You would think:
    delete doc..*.worm.(@type==”evil”);
    but you get the error “Delete operator is not supported with operand of type XMLList” – strange as you’d assume doc..*.worm is returning an XMLList too…

    You can go
    doc..*.worm.(@type==”evil”)[0];
    which would delete one of them (and naturally [1] to delete the other – but clearly not helpful) – so does that mean looping over the XMLList is the only way to delete multiple nodes based on a filter criteria? Be a bit of a shame if that is the case – hopefully you can tell me I’m missing something obvious??

  2. I’d like more info on it too.

    I think it’s safe to say you can’t delete an E4X expression operator “()”, but you can delete an XML node of it.
    and all of the nodes nested in that node….by using [index] bracket operator on it

    Yep its strange. The return datatype of this syntax “doc..*.worm” is an XMLList.

    doc..*.worm //technically this is XMLList but delete works when the E4X syntax DOES NOT have an expression.
    doc..*.(name()==”worm”) //The return type is XMLList and delete does not work with XMLList.
    doc..*.(name()==”worm”)[0] //The return type is XML and delete works for XML.

    The “Expression” part of E4X syntax always returns an XMLList.
    The delete operator does not work with XMLList.
    delete doc..*.(name()==”worm”);//TypeError: Error #1119: Delete operator is not supported

    More strange confusion when I test:

    trace(”Testing ‘typeof’”);
    trace(typeof doc..*.worm); //says its XML an not XMLList
    trace(typeof doc..*.(name()==”worm”)); //also says its XML an not XMLList
    trace(”");
    trace(”Testing ‘is’”);
    trace(doc..*.worm is XML);
    trace(doc..*.(name()==”worm”) is XML);
    trace(”");

  3. Yeah it doesn’t really seem too logical does it? Just think that I must be missing some trick here, but there you go!

    I think typeof will return ‘XML’ no matter if it’s XML or XMLList every time – you know like typeof on an Array is always ‘object’, but it is interesting that using ‘is’ gives false for is XML, true for is XMLList – yet you can delete (i.e. no error #1119) when the XMLList wasn’t made using a filter. Really weird.

    Ah well, looping it is! For now…

  4. You’re awesome. That “[" "]” solution for the warning of RegExp .test fixed my warnings. Thanks!

    Dom

Leave a Comment

Thanks for visiting www.keith-hair.net