2010-01-11 34 views
10

Tengo el siguiente código que se aplica un estilo XSLTChrome y Safari XSLT utilizando JavaScript

Test.Xml.xslTransform = function(xml, xsl) { 
    try { 
     // code for IE 
     if (window.ActiveXObject) { 
      ex = xml.transformNode(xsl); 
      return ex; 
     } 
     // code for Mozilla, Firefox, Opera, etc. 
     else if (document.implementation && document.implementation.createDocument) { 
      xsltProcessor = new XSLTProcessor(); 
      xsltProcessor.importStylesheet(xsl); 
      resultDocument = xsltProcessor.transformToFragment(xml, document); 
      return resultDocument; 
     } 
    } catch (exception) { 
     if (typeof (exception) == "object") { 
      if (exception.message) { 
       alert(exception.message); 
      } 
     } else { 
      alert(exception); 
     } 
    } 

El código está trabajando en IE y Firefox, pero no en Chrome y Safari. ¿Alguna idea de por qué?

actualización

ResultDocument = xsltProcessor.transformToFragment(xml, document); 

La línea anterior está volviendo nula. No se arrojó ningún error.

actualización

El código no está funcionando como el archivo XSL XSLT contiene: include. Necesidad de encontrar una manera de conseguir el trabajo incluyen voy a pegar aquí el progreso

actualización

Se ha recomendado que utilizo el plugin http://plugins.jquery.com/project/Transform/. Estoy intentando utilizar la biblioteca del lado del cliente como el ejemplo de incluir trabajos aquí (http://daersystems.com/jquery/transform/).

El código funciona en IE pero aún no está en cromo.

Test.Xml.xslTransform = function(xml, xsl) { 
     try { 
       $("body").append("<div id='test' style='display:none;'></div>"); 
       var a = $("#test").transform({ xmlobj: xml, xslobj: xsl }); 
       return a.html(); 
     } 
     catch (exception) { 
      if (typeof (exception) == "object") { 
       if (exception.message) { 
        alert(exception.message); 
       } 
      } else { 
       alert(exception); 
      } 

     } 
    } 

XML y XSL son ambos objetos se pasan en.

actualización

He intentado cambiar el archivo XSL a ser algo muy simple, sin incluir y Chrome todavía no está aplicando la hoja de estilo e IE es. El XSL que está siendo traído como un objeto es:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:rs="urn:schemas-microsoft-com:rowset" 
    xmlns:z="#RowsetSchema" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:spsoap="http://schemas.microsoft.com/sharepoint/soap/" 
    > 
    <xsl:output method="html"/> 
    <xsl:template match="/"> 
     <h1>test</h1> 
    </xsl:template> 

</xsl:stylesheet> 

actualización

El resultado final que yo quiero es que el XSL que se aplicará al archivo XML. El archivo xsl tiene incluido. Quiero que la transferencia ocurra en el cliente idealmente.

actualizado Rupert se puede actualizar a la pregunta con el XML y cómo lo está llamando Test.Xml.xslTransform?

que tiene el código XML usando IE8

<?xml version="1.0"?> 
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><SearchListItemsResponse xmlns="http://schemas.microsoft.com/sharepoint/soap/"><SearchListItemsResult><listitems xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:rs="urn:schemas-microsoft-com:rowset" xmlns:z="#RowsetSchema"> 
        <rs:data ItemCount="1"> 
         <z:row ows_Title="Test" ows_FirstName="Test 4" ows_UniqueId="74;#{1A16CF3E-524D-4DEF-BE36-68A964CC24DF}" ows_FSObjType="74;#0" ows_MetaInfo="74;#" ows_ID="74" ows_owshiddenversion="10" ows_Created="2009-12-29 12:21:01" ows_FileRef="74;#Lists/My List Name/74_.000" ReadOnly="False" VerificationRequired="0"/> 
        </rs:data> 
       </listitems></SearchListItemsResult></SearchListItemsResponse></soap:Body></soap:Envelope> 

El código está siendo llamado de la siguiente manera:

xsl = Test.Xml.loadXMLDoc("/_layouts/xsl/xsl.xslt"); 
var doc = Test.Xml.xslTransform(xData.responseXML, xsl); 

XDATA es el XML devuelto por un servicio web.

+0

Proporcione más información, como el mensaje de excepción. Recomiendo usar Sarissa (JavaScript de código abierto para XML/XSLT entre navegadores). –

+0

Quizás el XSLT en el XML no devuelva ningún resultado porque ninguna de las plantillas en el XSLT coincide en el documento XML. Ver mi blog "Evitar errores XSLT comunes" (http://dev.ektron.com/blogs.aspx?id=22956), especialmente el enlace "XSLT: espacios de nombres" (http://dev.ektron.com/kb_article.aspx ? id = 481) –

+0

Parece que hay un problema al usar xsl: include en xslt. En busca de formas alrededor de este momento. – Rupert

Respuesta

14

Si su XSLT usa xsl:include, puede recibir extraños errores inexplicables pero siempre con el mismo resultado final: su transformación falla.

Consulte este informe de errores de cromo y apúntelo! http://code.google.com/p/chromium/issues/detail?id=8441

Sin embargo, el error está en el webkit. Para obtener más información here's otro enlace que entra en más detalles por qué no funciona.

La única forma de evitar esto es preprocesar la hoja de estilos para que se inyecte las hojas de estilo incluidas. Que es lo que una biblioteca XSLT de navegación cruzada como Sarissa hará por ti automáticamente.

Si busca la solución jQuery:
http://plugins.jquery.com/project/Transform/ es un complemento XSL de navegador cruzado. Lo he usado con éxito para hacer que xsl:include funcione en el pasado sin mucha molestia. No tiene que volver a escribir su xsl, este complemento lo procesará previamente por usted. Definitivamente vale la pena mirar, ya que es más ligero que Sarissa.

ACTUALIZACIÓN: página HTML

<html> 
<head> 
<script language="javascript" src="jquery-1.3.2.min.js"></script> 
<script language="javascript" src="jquery.transform.js"></script> 
<script type="text/javascript"> 
function loadXML(file) 
{ 
    var xmlDoc = null; 
    try //Internet Explorer 
    { 
     xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); 
     xmlDoc.async=false; 
     xmlDoc.load(file); 
    } 
    catch(e) 
    { 
     try //Firefox, Mozilla, Opera, etc. 
     { 
      xmlDoc=document.implementation.createDocument("","",null); 
      xmlDoc.async=false; 
      xmlDoc.load(file); 
     } 
     catch(e) 
     { 
      try //Google Chrome 
      { 
       var xmlhttp = new window.XMLHttpRequest(); 
       xmlhttp.open("GET",file,false); 
       xmlhttp.send(null); 
       xmlDoc = xmlhttp.responseXML.documentElement; 
      } 
      catch(e) 
      { 
      error=e.message; 
      } 
     } 
    } 
    return xmlDoc; 
} 
function xslTransform(xmlObject, xslObject) 
{ 
    try 
    { 
     $("body").append("<div id='test'></div>"); 
     var a = $("#test").transform({ xmlobj: xmlObject, xslobj: xslObject }); 
    } 
    catch (exception) 
    { 
     if (typeof (exception) == "object" && exception.message) 
      alert(exception.message); 
     else alert(exception); 
    } 
} 
var xmlObject = loadXML("input.xml"); 
var xslObject = loadXML("transform.xsl"); 
$(document).ready(function() 
{ 
    xslTransform(xmlObject, xslObject); 
}); 
</script> 
</head> 
<body> 

</body> 
</html> 

Esta prueba funciona tanto en Chrome/Firefox/IE.

input.xml es solo un archivo xml simple que contiene <root /> transform.xsl es el xsl eliminado que ha publicado.

EDITAR

Sin embargo, sí parece que el $ .transform tiene problemas al importar hojas de estilo de archivos incluidos:

Aquí está cómo solucionar este problema:

Localizar

var safariimportincludefix = function(xObj,rootConfig) { 

en jquery.transform.js y reemplace toda la función con esto:

var safariimportincludefix = function(xObj,rootConfig) { 
    var vals = $.merge($.makeArray(xObj.getElementsByTagName("import")),$.makeArray(xObj.getElementsByTagName("include"))); 

    for(var x=0;x<vals.length;x++) { 
     var node = vals[x]; 
     $.ajax({ 
      passData : { node : node, xObj : xObj, rootConfig : rootConfig}, 
      dataType : "xml", 
      async : false, 
      url : replaceref(node.getAttribute("href"),rootConfig), 
      success : function(xhr) { 
       try { 
        var _ = this.passData; 
        xhr = safariimportincludefix(xhr,_.rootConfig); 

        var imports = $.merge(childNodes(xhr.getElementsByTagName("stylesheet")[0],"param"),childNodes(xhr.getElementsByTagName("stylesheet")[0],"template")); 
        var excistingNodes = []; 
        try 
        { 
         var sheet = _.xObj; 
         var params = childNodes(sheet,"param"); 
         var stylesheets = childNodes(sheet,"template"); 
         existingNodes = $.merge(params,stylesheets); 
        } 
        catch(exception) 
        { 
         var x = exception; 
        } 
        var existingNames = []; 
        var existingMatches = []; 
        for(var a=0;a<existingNodes.length;a++) { 
         if(existingNodes[a].getAttribute("name")) { 
          existingNames[existingNodes[a].getAttribute("name")] = true; 
         } else { 
          existingMatches[existingNodes[a].getAttribute("match")] = true; 
         } 
        } 

        var pn = _.node.parentNode; 
        for(var y=0;y<imports.length;y++) { 
         if(!existingNames[imports[y].getAttribute("name")] && !existingMatches[imports[y].getAttribute("match")]) { 
          var clonednode = _.xObj.ownerDocument.importNode(imports[y],true); 
          //pn.insertBefore(clonednode,_.xObj); 
          pn.insertBefore(clonednode,childNodes(_.xObj,"template")[0]); 
         } 
        } 
        pn.removeChild(_.node); 
       } catch(ex) { 

       } 
      } 
     }); 
    } 

    return xObj; 
}; 

Ahora, utilizando la prueba previamente pegado index.html esto para transform.xsl:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    > 
     <xsl:include href="include.xsl" /> 
    <xsl:output method="html"/> 
    <xsl:template match="/"> 
      <xsl:call-template name="giveMeAnIncludedHeader" /> 
    </xsl:template> 
</xsl:stylesheet> 

Y esto por include.xsl

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:template name="giveMeAnIncludedHeader"> 
     <h1>Test</h1> 
    </xsl:template> 
</xsl:stylesheet> 

Con la corrección previamente publicado en jquery.transform.js esto ahora se inserte incluido <h1>Test</h1> en todos los navegadores.

Se puede ver en acción aquí: http://www.mpdreamz.nl/xsltest

+0

Parece ser el problema xsl: include que está causando el problema. Estoy buscando posiblemente tratando de usar Sarissa – Rupert

+0

Actualizado con otra biblioteca que tiene como objetivo arreglar esto. El plugin jQuery es fácil de configurar y no tiene que volver a escribir su xslt, que es un gran ahorro de tiempo, incluso si el procesamiento previo agregará algo de latencia. –

+0

Creo que el problema que tendré es que el archivo xml se está generando sobre la marcha, así que no creo que la función de transformación funcione. – Rupert

5

Ésta no es una respuesta a la pregunta original, pero durante mi búsqueda a través de Internet en busca de una transformación XSLT muestra que funciona en el cromo he encontrado enlaces a este hilo muchas veces. Estaba buscando una solución que no utilizara librerías/plugins de fuente abierta o de terceros y que funcione bien con Silverlight.

El problema con Chrome y Safari es la limitación que impide cargar archivos XML directamente. La solución sugerida en http://www.mindlence.com/WP/?p=308 es cargar el archivo xml a través de cualquier otro método y pasarlo como una cadena al procesador xslt.

Con este enfoque pude realizar transformaciones xsl en javascript y pasar el resultado a la aplicación silverlight a través de HTML Bridge.

Cuestiones relacionadas