javascript XSLTProcessor ocasionalmente não funciona
-
01-07-2019 - |
Pergunta
A seguir JavaScript supõe para ler os tags mais populares de um arquivo XML e aplica a folha de estilo XSL e saída para o navegador como 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();
O problema com este script é em algum momento ele consegue saída o código HTML resultante, em algum momento isso não acontece. Alguém sabe onde está indo errado?
Solução
Você é obrigado na solução síncrona que você está usando agora, ou é uma solução assíncrona uma opção bem? Lembro-me de Firefox teve quota de problemas com chamadas síncronas no passado, e eu não sei o quanto de que ainda é realizada com ele. Já vi situações em que toda a interface do Firefox poderia bloquear-se durante o tempo que o pedido foi executado (que, dependendo das configurações de tempo limite, pode levar um tempo muito longo).
Seria necessário um pouco mais de trabalho em sua extremidade, mas a solução seria algo como o seguinte. Este é o uso I código para lidar com coisas XSLT com Ajax (reescreveu-lo um pouco, porque o meu código é orientado a objeto e contém um loop que analisa o documento XSL apropriado a partir do documento XML carregado pela primeira vez)
Nota: Certifique-se de declarar a sua versão do oCurrentRequest e oXMLRequest fora das funções, uma vez que irá transitar
.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();
}
}
Depois disto você só precisa de uma função chamada processReqChange que contém algo como o seguinte:
function processReqChange()
{
if (oCurrentRequest.readyState == 4)
{
if (oCurrentRequest.status == 200)
{
oXMLRequest = oCurrentRequest;
oCurrentRequest = null;
loadXSLDoc();
}
}
}
E claro que você vai precisar para produzir um segundo conjunto de funções para lidar com a carga de XSL (a partir de loadXSLDoc sobre, por exemplo).
Então, no final de você processXSLReqChange você pode pegar o seu resultado XML e XSL resultado e fazer a transformação.
Outras dicas
Bem, isso código segue caminhos completamente diferentes para IE e tudo-else. Presumo que o problema está limitado a um deles. Quais navegadores você já tentou-o, e que exibem esse erro?
A única outra coisa que eu posso pensar é que o elemento popularTags não pode existir quando você está tentando fazer coisas para ele. Como é que esta função que está sendo executado? Em um / evento domready onload?
Dan. IE executa o script com nenhum problema. Eu estou enfrentando o problema no Firefox. O elemento popularTags existe no documento HTML que chama a função.
<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>
Para evitar problemas com as coisas de carga em paralelo (como sugerido por Dan), é sempre uma boa idéia para chamar tais scripting apenas quando a página foi totalmente carregado.
O ideal é colocar o script-tags na cabeça da página e ShowPopularTags call (); no item OnLoad corpo. I.
<BODY onLoad="ShowPopularTags();">
Dessa forma, você está completamente certo de que seus document.getElementById ( "popularTags") não falha porque o script é chamado antes do HTML que contém o elemento está totalmente carregado.
Além disso, podemos ver a sua função XMLDocLoad? Se que contém elementos não-seqüenciais, bem como, você pode estar enfrentando um problema onde a transformação XSLT ocorre antes dos objetos XML e XSL são totalmente carregado.
A seguir é a função 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'); } }