Flash中调用XML制作新闻发布(AS2.0 OOP)

2006-11-24 21:55 | Army


写本篇教程之前,我的初衷是用它们俩结合制作一个留言本。很可惜,后来我发现如果不借用另外的(脚本)语言的话,这是不可能做到的。AS只允许通过POST或GET这样的HTTP协议发送XML到指定的URL,并不能直接保存文件到服务器上(这也体现了安全所在)。所以,这里我只简要介绍一下如何加载XML以及以前处理它的一些经验。想要制作出具有交互功能的B/S的话,还是不推荐使用Flash作为中间的“交换站”的,除非你确实需要(比如Flash整站)或者纯粹想炫耀一番。

源文件地址是:
http://ff9.ffsky.cn/flash_teach\loadxml/exp.rar

exp.fla中的元素非常简单,一共4帧,第4帧上放了一个变量名为information的动态文本,它是多行有边框且呈现为HTML样式的。唯一的图形元件是个三角形,用以上下翻滚文字。

我们还是来先看一下message.xml文件:

<?xml version="1.0" encoding="utf-8"?>

<message>
  <name>army</name>
  <body>我是loli米!我今年15岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是正太米!我今年15岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是御姐米!我今年22岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是叔叔米!我今年22岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是大姨妈米!我今年……岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是xx米!我今年xx岁!</body>
</message>
<message>
  <name>army</name>
  <body>我是……别我是了,不嫌烦啊!怎么你看我不爽?那就来SM我吧!</body>
</message>


每个message节点有name和body子节点,它们有各自的内容。它是utf-8编码的,保存时务必使用这个编码,否则中文可能显示出错。
再来看看LoadXML.as文件:

[color=red]class LoadXML {  
  function startLoad():Void {
    var myxml:XML = new XML();
    myxml.load("message.xml");
    myxml.ignoreWhite = true;
    myxml.onLoad = function(success) {
      if (success) {
        trace("loading success!");
        var msgname = new Array(), msgbody = new Array();
        var temp = myxml.firstChild;
        var i:Number = 0;
        while(temp) {
          msgname[i] = temp.firstChild.firstChild.nodeValue;
          msgbody[i] = temp.firstChild.nextSibling.firstChild.nodeValue;
          //trace(i + ". " + temp.firstChild.firstChild.nodeValue + ":" + temp.firstChild.nextSibling.firstChild.nodeValue);
          temp = temp.nextSibling;
          i++;
        }
        //input into array;
        while(i > 0) {
          i--;
          _root.information += "<font color=\"#FF3333\">消息" + (i + 1) + ":" + "</font>\n";
          _root.information += " 名称" + ":" + msgname[i] + "\n";
          _root.information += " 内容" + ":" + msgbody[i] + "\n";
        }
        _root.nextframe();
      }
      else {
        trace("loading error!");
        _root.gotoAndPlay(2);
      }
    }
  }
}[/color]

在外部类文件中想要创建一个非基本类型的元素(比如一个xml类,或者其它的自定义类等),必须放在一个方法体中,否则编译器会报错。我很不喜欢这个规则,因为这就意味着一些内部类使用起来将会比较麻烦,甚至非常困难。作用域带来的种种困扰,让我感到编写时很不顺手,程序亦变得不易阅读。

这个类中只有1个startLoad方法。我原本想把它分成startLoad、intoArray、intoInfo三个方法,但迫于上述原因不得已合在了一起。
首先申明了一个名为myxml的XML类,然后调用其load方法,参数则是指定加载xml文件的路径。由于message.xml在相同目录下,因此加载时不必添加任何前缀。随后的ignoreWhite属性是指读取时是否忽略xml文件里的空白符(如回车、换行等),默认是false,这里我们必须显式地把它设置为true。
myxml.onLoad是一个具有布尔属性的方法,里面使用了一个if语句判断当xml文件加载成功时如何如何,而失败时又如何如何。这里我们着重介绍加载成功的部分。
msgname和msgbody是两个一维数组,用以存放从xml文件里读取来的数据。我们先将temp赋值到第一个xml节点上——就是那第一个message节点。
随后的while循环是存放到数组的过程,判断的条件是temp存在或为真。

while语句的介绍。一个小例子,很简单:
var i:Number = 0;
while(i <= 3) {
  trace(i);
  i++;
}
i的初值是0,循环条件是i不大于3,循环体中是输出i的值然后i自增。这样这个while将执行4次,输出结果就是0123。


我们将temp的一系列的字节点内容存放到msgname和msgbody数组中,然后将temp下移一个节点并且i自增以备循环。有人可能会对那一长串firstchild吓住,请不要担心,其实它很简单。firstchlid是指所指节点的第一个子节点,它可以无限嵌套下去;而nextsibling是指所指节点的同级下一个节点;nodevalue是指所指节点的值。我以第一次循环为例:
temp首先指向第一个message节点,这样,temp.firstChild.firstChild.nodeValue依次指到:message的name节点的“army”节点的内容——它就是文本“army”;temp.firstChild.nextSibling.firstChild.nodeValue依次指到:message的name节点的body节点的“我是loli米!我今年15岁!”节点的内容——它就是“我是loli米!我今年15岁!”。
如何,很冗繁的东西吧?没办法,它就是这么麻烦。最后一个nodeValue其实可以省略,因为本身已经指到文本节点上了,但却不能保留它而省略前面的firstchild。
第2个while循环以i大于0作为条件,把msgname和msgbody的数组按照一定的样式存放到根时间轴的information变量上,也就是那个动态文本。
循环中i自减,是因为i的值在上一个while中已经增大到数组长度-1了(数组下标以0为开始,所以是长度-1)。+=操作符是字符串链接,由于动态文本是接受HTML的,所以我把每个消息列表值都设成红色,\n是换行。
一切均已搞定,最后调用nextframe()方法把时间轴放到下一帧(第4帧)并停止,就能观测到整个的效果了。Flash内部还有一些调用对象的代码,它很简单:

第1帧创建对象。
var lx1:LoadXML = new LoadXML();

第3帧调用startLoad方法判断是否加载成功,否则返回第2帧重新来执行它。
lx1.startLoad();

第4帧的两个上下按钮。
on(release) {
  information.scroll ++;
}

on(release) {
  information.scroll --;
}


这个教程的技术含量并不高,相信很多人都能读懂。它只适用于一些简单的小功能的用途,比如新闻发布、资源列表等等。而它的更新确实很方便,只需更新xml文档即可。倘若你想借助xml制作留言本之类的东西可以查阅帮助文档中的loadVariables()用法,不过我还是建议绕过xml使用脚本语言与数据库直接打交到。