JavaScript XSLTProcessor が時々動作しない
-
01-07-2019 - |
質問
次の JavaScript は、XML ファイルから一般的なタグを読み取り、XSL スタイルシートを適用して HTML としてブラウザに出力することを想定しています。
function ShowPopularTags() {
xml = XMLDocLoad("http://localhost/xml/tags/popular.xml?s=94987898");
xsl = XMLDocLoad("http://localhost/xml/xsl/popular-tags.xsl");
if (window.ActiveXObject) {
// code for IE
ex = xml.transformNode(xsl);
ex = ex.replace(/\\/g, "");
document.getElementById("popularTags").innerHTML = ex;
} else if (document.implementation && document.implementation.createDocument) {
// code for Mozilla, Firefox, Opera, etc.
xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(xsl);
resultDocument = xsltProcessor.transformToFragment(xml, document);
document.getElementById("popularTags").appendChild(resultDocument);
var ihtml = document.getElementById("popularTags").innerHTML;
ihtml = ihtml.replace(/\\/g, "");
document.getElementById("popularTags").innerHTML = ihtml;
}
}
ShowPopularTags();
このスクリプトの問題は、結果の HTML コードを出力できる場合と出力できない場合があることです。どこが間違っているのか知っている人はいますか?
解決
現在使用している同期ソリューションを強制されていますか? それとも非同期ソリューションもオプションですか?Firefox には過去に同期呼び出しに関する問題がいくつかあったことを思い出しますが、その問題がどれくらいまだ残っているかはわかりません。リクエストが実行されている間、Firefox インターフェース全体がロックする状況を見たことがあります (タイムアウト設定によっては、非常に長い時間がかかる場合があります)。
もう少し作業が必要になりますが、解決策は次のようになります。これは、Ajax で XSLT のものを処理するために使用するコードです (コードはオブジェクト指向であり、最初にロードされた XML ドキュメントから適切な XSL ドキュメントを解析するループが含まれているため、少し書き直しました)
注記:oCurrentRequest と oXMLRequest のバージョンは引き継がれるため、必ず関数の外で宣言してください。
if (window.XMLHttpRequest)
{
oCurrentRequest = new XMLHttpRequest();
oCurrentRequest.onreadystatechange = processReqChange;
oCurrentRequest.open('GET', sURL, true);
oCurrentRequest.send(null);
}
else if (window.ActiveXObject)
{
oCurrentRequest = new ActiveXObject('Microsoft.XMLHTTP');
if (oCurrentRequest)
{
oCurrentRequest.onreadystatechange = processReqChange;
oCurrentRequest.open('GET', sURL, true);
oCurrentRequest.send();
}
}
この後は、次のような内容を含む processReqChange という名前の関数が必要になります。
function processReqChange()
{
if (oCurrentRequest.readyState == 4)
{
if (oCurrentRequest.status == 200)
{
oXMLRequest = oCurrentRequest;
oCurrentRequest = null;
loadXSLDoc();
}
}
}
そしてもちろん、XSL ロードを処理するための 2 番目の関数セットを作成する必要があります (たとえば、loadXSLDoc から開始)。
次に、processXSLReqChange の最後に、XML 結果と XSL 結果を取得して、変換を実行できます。
他のヒント
そうですね、そのコードは IE とその他すべてでまったく異なるパスをたどります。問題はそのうちの 1 つに限定されていると思います。どのブラウザで試しましたか?どのブラウザでこのエラーが発生しましたか?
他に考えられる唯一のことは、popularTags 要素に何かを実行しようとしているときに、popularTags 要素が存在しない可能性があるということです。この機能はどのように実行されているのでしょうか?onload/domready イベント内ですか?
ダン。IE はスクリプトを問題なく実行します。Firefox で問題に直面しています。PopularTags 要素は、関数を呼び出す HTML ドキュメント内に存在します。
<div id="popularTags" style="line-height:18px"></div> <script language="javascript" type="text/javascript"> function ShowPopularTags() { xml=XMLDocLoad("http://localhost/xml/tags/popular.xml?s=29497105"); xsl=XMLDocLoad("http://localhost/xml/xsl/popular-tags.xsl"); if (window.ActiveXObject){ // code for IE ex=xml.transformNode(xsl); ex = ex.replace(/\\/g, ""); document.getElementById("popularTags").innerHTML=ex; } else if (document.implementation && document.implementation.createDocument){ // code for Mozilla, Firefox, Opera, etc. xsltProcessor=new XSLTProcessor(); xsltProcessor.importStylesheet(xsl); resultDocument = xsltProcessor.transformToFragment(xml,document); document.getElementById("popularTags").appendChild(resultDocument); var ihtml = document.getElementById("popularTags").innerHTML; ihtml = ihtml.replace(/\\/g, ""); document.getElementById("popularTags").innerHTML = ihtml; } } ShowPopularTags(); </script>
(Dan が示唆したように) 並列ロードの問題を回避するには、ページが完全にロードされたときにのみそのようなスクリプトを呼び出すことをお勧めします。
理想的には、スクリプトタグをページヘッドに配置し、Show PopularTags() を呼び出します。本体のオンロード項目。つまり、
<BODY onLoad="ShowPopularTags();">
そうすることで、要素を含む HTML が完全に読み込まれる前にスクリプトが呼び出されるために、 document.getElementById("popularTags") が失敗しないことが完全に保証されます。
また、XMLDocLoad 関数も確認できますか?これに非順次要素も含まれている場合は、オブジェクト xml および xsl が完全にロードされる前に XSLT 変換が行われるという問題に直面する可能性があります。
以下は XMLDocLoad 関数です。
function XMLDocLoad(fname) { var xmlDoc; if (window.ActiveXObject){ // code for IE xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async=false; xmlDoc.load(fname); return(xmlDoc); } else if(document.implementation && document.implementation.createDocument){ // code for Mozilla, Firefox, Opera, etc. xmlDoc=document.implementation.createDocument("","",null); xmlDoc.async=false; xmlDoc.load(fname); return(xmlDoc); } else{ alert('Your browser cannot handle this script'); } }