Pregunta

El siguiente JavaScript supone leer las etiquetas populares de un archivo XML y aplicar la hoja de estilo XSL y la salida al 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();

El problema con este script es que en ocasiones logra generar el código HTML resultante y en otras no.¿Alguien sabe dónde va mal?

¿Fue útil?

Solución

¿Se ve obligado a utilizar la solución sincrónica que está utilizando ahora o también es una opción una solución asincrónica?Recuerdo que Firefox ha tenido algunos problemas con las llamadas sincrónicas en el pasado, y no sé cuánto de eso todavía persiste.He visto situaciones en las que toda la interfaz de Firefox se bloqueaba mientras se ejecutaba la solicitud (lo cual, dependiendo de la configuración del tiempo de espera, puede llevar mucho tiempo).

Requeriría un poco más de trabajo de su parte, pero la solución sería algo como lo siguiente.Este es el código que uso para manejar cosas XSLT con Ajax (lo reescribí ligeramente porque mi código está orientado a objetos y contiene un bucle que analiza el documento XSL apropiado a partir del documento XML cargado por primera vez).

Nota:asegúrese de declarar su versión de oCurrentRequest y oXMLRequest fuera de las funciones, ya que se transferirá.

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();
  }
}

Después de esto, solo necesitarás una función llamada ProcessReqChange que contenga algo como lo siguiente:

function processReqChange()
{
  if (oCurrentRequest.readyState == 4)
  {
    if (oCurrentRequest.status == 200)
    {
      oXMLRequest = oCurrentRequest;
      oCurrentRequest = null;
      loadXSLDoc();
    }
  }
}

Y, por supuesto, necesitará producir un segundo conjunto de funciones para manejar la carga XSL (a partir de loadXSLDoc, por ejemplo).

Luego, al final de su proceso XSLReqChange, puede tomar el resultado XML y el resultado XSL y realizar la transformación.

Otros consejos

Bueno, ese código sigue caminos completamente diferentes para IE y todo lo demás.Supongo que el problema se limita a uno de ellos.¿En qué navegadores lo ha probado y cuáles presentan este error?

La única otra cosa que se me ocurre es que es posible que el elemento popularTags no exista cuando intentas hacerle cosas.¿Cómo se ejecuta esta función?¿En un evento onload/domready?

Dan.IE ejecuta el script sin problemas.Estoy enfrentando el problema en Firefox.El elemento popularTags existe en el documento HTML que llama a la función.

<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 con la carga de elementos en paralelo (como lo insinuó Dan), siempre es una buena idea llamar a dichas secuencias de comandos solo cuando la página se haya cargado por completo.

Lo ideal sería colocar las etiquetas de script en el encabezado de la página y llamar a ShowPopularTags();en el cuerpo Cargar elemento.Es decir.

<BODY onLoad="ShowPopularTags();">

De esa manera, estará completamente seguro de que su document.getElementById("popularTags") no falla porque se llama a la secuencia de comandos antes de que el HTML que contiene el elemento esté completamente cargado.

Además, ¿podemos ver su función XMLDocLoad?Si eso también contiene elementos no secuenciales, es posible que tenga un problema en el que la transformación XSLT tenga lugar antes de que los objetos xml y xsl estén completamente cargados.

La siguiente es la función 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');
    }


}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top