1

Flash 内のさまざまな種類の XML (具体的には、FeedBurner RSS ファイルと YouTube Data API 応答) の解析で問題が発生しています。を使用しURLLoaderて XML ファイルをロードしEvent.COMPLETE、新しい XML オブジェクトを作成しています。これは 75% の確率で問題なく動作しますが、時々、次のような例外が発生します。

TypeError: Error #1085: The element type "link" must be terminated by the matching end-tag "</link>".

問題は XML が大きいことでありEvent.COMPLETE、XML が実際に からダウンロードされる前にイベントが発生した可能性がありURLLoaderます。私たちが思いついた唯一の解決策は、イベント時にタイマーを設定し、基本的に「数秒待ってから」データの解析を開始することです。確かに、これはこれを行うための最良の方法ではありません。

Flash 内で XML を解析する確実な方法はありますか?

更新 2008 年 9 月 2 日次の結論に達しました。この時点でコード内で例外が発生します。

data = new XML(mainXMLLoader.data);

//  calculate the total number of entries.
for each (var i in data.channel.item){
    _totalEntries++;
}

この部分に try/catch ステートメントを配置し、現在、エラーが発生したときに画面にエラー メッセージを表示しています。私の質問は、不完全なファイルがどのようにしてこの時点に到達するbytesLoaded == bytesTotalかです。


元の質問をステータス レポートで更新しました。別の質問は、データにアクセスする前にオブジェクトが適切に解析されているかどうかを判断する方法があると思いXMLます (エラーが、XML が実際にオブジェクトに解析される前にオブジェクトの数をカウントするループが開始されている場合) ?


@Theo:ignoreWhitespace のヒントをありがとう。また、準備が整う前にイベントが呼び出されていることも確認しました (いくつかのテスト トレースを行いました)。mainXMLLoader.bytesLoaded + "/" + mainXMLLoader.bytesLoaded

4

10 に答える 10

1

ちなみに、このステートメントは効果がありません。

XML.ignoreWhitespace;

ignoreWhitespaceはプロパティだからです。次のように設定する必要がありますtrue

XML.ingoreWhitespace = true;
于 2008-08-22T07:27:47.190 に答える
1

私にとって懸念されることは、ロードが完了する前に Event.COMPLETE を起動している可能性があることです。これにより、ロードがタイムアウトしているのかどうか疑問に思います。

問題はどのくらいの頻度で発生しますか? 同じフィードで、ある瞬間に成功し、次の瞬間に失敗することはありますか?

テスト目的で、ハンドラー メソッドの上部にあるURLLoader.bytesLoadedとをトレースしてみてください。それらが一致しない場合は、イベントが時期尚早に起動していることがわかります。この場合、URLLoader の進行イベントをリッスンできます。ハンドラーで をチェックし、読み込みが完全に完了してからのみ XML を解析してください。確かに、これはおそらく URLLoader が起動する前に行っていることと似ていますが、それが壊れている場合は、独自のロールを試すことができます。URLLoader.bytesTotalEvent.COMPLETEbytesLoadedbytesTotalEvent.COMPLETE

あなたが見つけたことを私たちに知らせてください。できれば、ソースコードを貼り付けてください。注目すべき何かを見つけることができるかもしれません。

于 2008-08-20T16:54:12.570 に答える
1

ロードされたバイト数が合計バイト数と同じであることを確認してみましたか?

URLLoader.bytesLoaded == URLLoader.bytesTotal

ファイルの読み込みが完了したかどうかはわかりますが、完了イベントが早期に発生するのには役立ちませんが、xml に問題があるかどうかはわかります。

私のxmlは常に同じサイトにあるため、ドメインで機能するかどうかはわかりません。

于 2008-08-20T13:36:43.027 に答える
0

ローダーが完全にロードされていない限り、Event.COMPLETEハンドラーを呼び出すべきではありません。意味がありません。bytesLoaded(トレースするvs.bytesTotal値を見て)実際に完全にロードされていないことを確認しましたか?Event.COMPLETEそれ以前にイベントがディスパッチされた場合、bytesLoaded == bytesTotalそれはバグです。

タイマーで動作するのは良いことですが、それが必要になるのは非常に奇妙です。

于 2008-08-22T07:32:57.800 に答える
0

さらにコードを投稿していただければ、問題を見つけることができるかもしれません。

(トレース以外に)テストするもう1つのことは、ハンドラー内のローダーのプロパティbytesTotalをトレースして、XMLデータが実際に正しくロードされたかどうかを確認することです。たとえば、そこにあるかどうかを確認します。dataEvent.COMPLETE</link>

于 2008-08-21T14:13:37.923 に答える
0

XML ドキュメントの最後に、「true」に等しい 1 つの属性「値」を持つ一意の要素名前空間を設定できます。

//The XML
//Flash ignores the line that specifies the XML version and encoding so I have here as well.

<parent>
    <child name="child1" />
    <child name="child2" />
    <child name="child3" />
    <child name="child4" />
    <documentEnd value="true" />
</parent>

//Sorry about the spacing, but it is difficult to get XML to show.

//Flash
var loader:URLLoader = new URLLoader();
var request:URLRequest = new URLRequest('pathToXML/xmlFileName.xml');

var xml:XML;

//Event Listener with weak reference set to true (5th parameter);
//The above comment does not define a required practice, this is to aid with garbage collection.

loader.addEventListener(Event.COMPLETE, onXMLLoadComplete, false, 0, true);
loader.load(request);
function onXMLLoadComplete(e:Event):void
{
   xml = new XML(e.target.data);

   //Now we check the last element (child) to see if it is documentEnd.
   if(xml[xml.length()-1].documentEnd.@value == "true")
   {
      trace("Woot, it seems your xml made it!");
   }
   else
   {
      //Attempt the load again because it seems it failed when it was unable to find documentEnd in the XML Object.
      loader.load(request);
   }
}

今のところ、これがお役に立てば幸いですが、本当の望みは、十分な数の人がこの問題について Adob​​e に知らせてくれることです。イベントに頼れないのは悲しいことです。ただし、XML について聞いたところによると、XML は大規模にはあまり最適ではなく、データをシリアル化するために AMFPHP のようなものが必要な場合だと思います。

お役に立てれば!ここでの考え方は、XML の最後の子/要素が何であるかは、設定​​したことでわかっているということです! 最後の子/要素にアクセスできない理由はありませんが、アクセスできない場合は、XML が実際には完全ではないと想定し、強制的に再度ロードする必要があります。

于 2008-09-25T08:27:43.600 に答える
0

@Brian Warshaw: この問題は、約 10 ~ 20% の確率でしか発生しません。時々、問題が発生し、アプリをリロードするだけで問題なく動作することもあります。

これは元のコードです(質問したとき):

public class BlogReader extends MovieClip {
    public static const DOWNLOAD_ERROR:String = "Download_Error";
    public static const FEED_PARSED:String = "Feed_Parsed";

    private var mainXMLLoader:URLLoader = new URLLoader();
    public var data:XML;
    private var _totalEntries:Number = 0;

    public function BlogReader(url:String){
        mainXMLLoader.addEventListener(Event.COMPLETE, LoadList);
        mainXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, errorCatch);
        mainXMLLoader.load(new URLRequest(url));
        XML.ignoreWhitespace;
    }
    private function errorCatch(e:IOErrorEvent){
        trace("Oh noes! Yous gots no internets!");
        dispatchEvent(new Event(DOWNLOAD_ERROR));
    }
    private function LoadList(e:Event):void {
        data = new XML(e.target.data);

        //  calculate the total number of entries.
        for each (var i in data.channel.item){
            _totalEntries++;
        }

        dispatchEvent(new Event(FEED_PARSED));
    }
}

そして、これは Re0sless の元の返信に基づいて私が書いたコードです (言及されたいくつかの提案に似ています):

public class BlogReader extends MovieClip {
    public static const DOWNLOAD_ERROR:String = "Download_Error";
    public static const FEED_PARSED:String = "Feed_Parsed";

    private var mainXMLLoader:URLLoader = new URLLoader();
    public var data:XML;
    protected var _totalEntries:Number = 0;

    public function BlogReader(url:String){
        mainXMLLoader.addEventListener(Event.COMPLETE, LoadList);
        mainXMLLoader.addEventListener(IOErrorEvent.IO_ERROR, errorCatch);
        mainXMLLoader.load(new URLRequest(url));
        XML.ignoreWhitespace;
    }
    private function errorCatch(e:IOErrorEvent){
        trace("Oh noes! Yous gots no internets!");
        dispatchEvent(e);
    }
    private function LoadList(e:Event):void {
        isDownloadComplete();           
    }
    private function isDownloadComplete() {
        trace (mainXMLLoader.bytesLoaded + "/" + mainXMLLoader.bytesLoaded);
        if (mainXMLLoader.bytesLoaded == mainXMLLoader.bytesLoaded){
            trace ("xml fully loaded");

            data = new XML(mainXMLLoader.data);

            //  calculate the total number of entries.
            for each (var i in data.channel.item){
                _totalEntries++;
            }

            dispatchEvent(new Event(FEED_PARSED));
        } else {
            trace ("xml not fully loaded, starting timer");
            var t:Timer = new Timer(300, 1);
            t.addEventListener(TimerEvent.TIMER_COMPLETE, loaded);
            t.start();
        }
    }
    private function loaded(e:TimerEvent){
        trace ("timer finished, trying again");
        e.target.removeEventListener(TimerEvent.TIMER_COMPLETE, loaded);
        e.target.stop();

        isDownloadComplete();
    }
}

問題が発生していないかどうかを判断するコードを追加して以来mainXMLLoader.bytesLoaded == mainXMLLoader.bytesLoaded、このバグを再現するのは難しいため、私が知っている限り、何も修正しておらず、代わりに役に立たないコードを追加したことを指摘します。

于 2008-08-21T17:42:08.810 に答える
0

あなたの質問で述べたように、問題は、プログラムが実際に完全にダウンロードされる前に XML を見ている可能性が非常に高いです。XML を「解析」する確実な方法があるかどうかはわかりません。コードは問題ない可能性が高く、単に実際にダウンロードされたかどうかの問題です。

ProgressEvent.PROGRESS イベントを使用して XML をダウンロードしながら継続的に監視し、Re0sless が示唆するように、bytesLoaded と bytesTotal をチェックし、Event.COMPLETE イベントを使用する代わりに、2 つの数値が等しいときに XML 解析を開始することができます。 .

ファイルにアクセスできれば、そのバイト情報にアクセスできます。

于 2008-08-20T16:36:44.657 に答える
0

https://bugs.adobe.com/flashplayer/でバグ レポートを提出することをお勧めします。これは、すべてのバイトが読み込まれる前にイベントが実際に発生するべきではないためです。それまでの間、タイマーと一緒に暮らす必要があると思います。代わりに進行状況イベントをリッスンすることで同じことができる場合があります。これにより、タイマーを自分で処理する必要がなくなる可能性があります。

于 2008-08-24T14:00:38.243 に答える
0

RSS サーバー ページは、常にアクセスしている場合は特に、正確で有効な XML データを吐き出すことができないことがあります。サーバーの応答が常に有効であることを確認するために、Web ブラウザー (できれば xml バリデータープラグインを使用) でページにアクセスしてみましたか?

ここで確認できる他の唯一のものは、次の行です。

xml = new XML(event.target.data);

//the data should already be XML, so only casting is necessary
xml = XML(event.target.data);

また、urlloader dataFormat を URLLoaderDataFormat.TEXT に設定し、prama-no-cache の URL ヘッダーを追加したり、URL にキャッシュ バスターを追加したりしましたか?

いくつかの提案...

于 2009-08-17T10:30:55.820 に答える