|
Introduction to XML in Flash
by senocular
Additional Helpful Methods
Let's not stop with what Macromedia
has provided for us to edit XML in Flash. We
can take that framework and build more useful
and straight-forward methods to further help
in editing XML content while in Flash. In fact,
maybe we can take what's been given to us and
make them better. The following represents a
few examples that add methods to the XMLNode
object and/or the XML object in Flash.*
- // formats XML into
a multi-lined, indented format
- // a good toString
replacement for XML with ignoreWhite = true
- XMLNode.prototype.format
= function(indent){
- if (indent
== undefined)
indent =
"";
- var str
= "";
- var currNode
= this.firstChild;
- do{
- if (currNode.hasChildNodes()){
- str +=
indent
+ currNode.cloneNode(0).toString().slice(0,-2)
+ ">\n";
- str +=
currNode.format(indent+"\t");
- str +=
indent
+ "</"
+ currNode.nodeName
+ ">\n";
- }else{
- str +=
indent
+ currNode.toString()
+ "\n";
- }
- }while
(currNode
= currNode.nextSibling);
- return str;
- }
- // moves a child within
its set of children (to before a beforeNode)
- XMLNode.prototype.moveBefore
= function(beforeNode){
- beforeNode.parentNode.insertBefore(
this.cloneNode(true),
beforeNode);
- this.removeNode();
- }
- // adds a root property that references the document root
- // element of an XML instance through any of its nodes
- XMLNode.prototype.root = function(){
- var r = this;
- while(r.parentNode) r = r.parentNode;
- return r.firstChild;
-
- };
- XMLNode.prototype.addProperty("root",
- function(){
- return this.root();
- },
- function(n){
- r = this.root();
- r.parentNode.appendChild(n);
- r.removeNode();
- }
- );
- // adds a firstNodes property (read-only) which returns
- // an array of all the nested first child elements within an
- // xml node. ex: firstChild.firstChild.firstChild == firstNodes[2]
- XMLNode.prototype.addProperty("firstNodes",
- function(){
- var c = [];
- var n = this;
- while(n = n.firstChild) c.push(n);
- return c;
- },null
- );
- // adds a text property that represents the text (nodeValue)
- // of a text node. This can be called from a text node *or* an
- // element which contains a text node (retrieves the last child)
- // making it easy to access text from an element which only
- // contains one text node
- XMLNode.prototype.text = function(){
- var n = this;
- if (n.nodeType == 1) n = this.lastChild;
- return n;
- }
- XMLNode.prototype.addProperty("text",
- function(){
- var n = this.text();
- if (n.nodeType == 3) return n.nodeValue;
- return "";
- },
- function(txt){
- var n = this.text();
- if (n.nodeType == 3) n.nodeValue = txt;
- else this.appendChild(new XML().createTextNode(txt));
- }
- );
- // Find a child element
by name and index (nth element of that name)
- XMLNode.prototype.findChild
= function(name,
index){
- var count
= 0;
- var currNode
= this.firstChild;
- do{
- if (currNode.nodeName
== name){
- count++;
- if (count
== index)
return
currNode;
- }
- }while
(currNode
= currNode.nextSibling);
- return false;
- }
- // Removes and returns
an XML node based on index
- XMLNode.prototype.extractChild
= function(i){
- var n
= this.childNodes[i].cloneNode(true);
- this.childNodes[i].removeNode();
- return n;
- }
- // Swap the positions
of two child nodes within their parent's childNodes
array
- XMLNode.prototype.swapChildren
= function(i,
i2){
- if (i==i2)
return(0);
- if (i
> i2){
- var temp
= i;
- i =
i2; i2
= temp;
- }
- var n
= this.extractChild(i);
- var n2
= this.extractChild(i2-1);
- this.insertBefore(n2,
this.childNodes[i]);
- this.insertBefore(n,
this.childNodes[i2]);
- }
- // Sort child nodes
based on a compare function (uses a simple
quicksort)
- XMLNode.prototype.sortChildren
= function(cmp,
low,high)
{
- var a
= this.childNodes;
- if (cmp
== undefined)
cmp =
this.sortChildren.defaultCompare;
- if (low
== undefined)
low =
0;
- if (high
== undefined)
high =
a.length;
- var p
= a[low],
w =
low+1,
h =
high;
- while(w
< h)
{
- if (cmp(a[w],
p))
w++;
- else this.swapChildren(w,
(--h));
- }
- this.swapChildren(low,
(--w));
- if (w-low
> 1)
this.sortChildren(cmp,
low, w);
- if (high-h
> 1)
this.sortChildren(cmp,
h, high);
- }
-
- // A default sort
function for use in sortChildren
- XMLNode.prototype.sortChildren.defaultCompare
= function(a,b){
- return a.nodeName
<= b.nodeName;
- }
- // removes a node
but leaves all child nodes it contained in
its place
- XMLNode.prototype.explodeIntoParent
= function(){
- if (!this.parentNode)
return false;
- while (this.hasChildNodes()){
- this.parentNode.insertBefore(this.firstChild,
this);
- }
- this.removeNode();
- return true;
- }
- // gets the index
of the current node in its parent's childNodes
array
- XMLNode.prototype.getIndexInParent
= function(){
- var i
= 0,
node =
this;
- while (node
= node.previousSibling)
i++;
- return i;
- }
- // trims white space
around text
- // can be used to
remove white space around formatted text node
text
- _global.TrimWhiteSpace
= function(str){
- var beg
= 0,
end =
str.length-1;
- while (str.charAt(beg).isWhite())
beg++;
- while (str.charAt(end).isWhite())
end--;
- return str.slice(beg,
end+1);
- }
- // determines if a
string is made up of white space
- // used by TrimWhiteSpace
- String.prototype.isWhite
= function(){
- return !isNaN("
"+this+"
0");
- }
* All methods provided are in ActionScript
1.0 format. They will work, for the most part,
with AS 2.0 but would require that you not strictly
type your XML instances (or, rather, add the
methods used into the intrinsic class definition).
Extending XMLNode in ActionScript 2.0 is not
really an option as it's the XML class that
instantiates XMLNodes internally, not you. So
you have no way of controlling how they are
made and with using which constructor. It's
this kind of situation where the flexibility
of AS 1.0 really pays off.
You can find more such examples at Layer51
Prototypes. There's also XPath
implementation for Flash (AS1,
AS2)
provided by XFactor
Studio. XPath provides an alternate, more
user friendly means of addressing XML content.
|
|