2011-10-29 11 views
7

Tengo un pequeño problema, ¿hay alguna forma de incluir dinámicamente otro xsl? Por ejemplo:Incluye dinámicamente otros archivos XSL en XSLT

<xsl:variable name="PathToWeb" select="'wewe'"/> 
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" /> 

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" /> 
+0

use bvb1909

Respuesta

2

No puede hacer esto. Las razones son simples:

XSL expandirá primero xsl: include durante la compilación, antes de que haga cualquier otra cosa. En ese momento su "variable" no se conoce y no se puede conocer y no se puede cambiar la transformación compilada una vez que se compila. Además, el href es un localizador uniforme de recursos, no una expresión XPath, por lo tanto, no se puede expandir una variable en él.

+0

bien, pero eso es estúpido ... en php un simple include() resolvió este problema ... y realmente lo necesito, ¿por qué se desarrolla de esta manera? – Master345

+0

No sé por qué pero xslt! = Php Tengo miedo :) – FailedDev

+1

@Row Minds Esta es una traducción exacta de tu respuesta que comenzó con "ok, pero eso es estúpido". Aquí está: "Creo que es estúpido que un plátano no esté en mi boca exactamente y cada vez que quiera comer un plátano. Cuando como PHP, es delicioso". El hecho de que la tecnología mono-ulula (sustituya cualquier nombre aquí, quizás PHP) implemente una inclusión de la manera que desee de ninguna manera hace que sea incorrecto que la tecnología diferente-mono-ulula (sustituya cualquier nombre aquí, tal vez xsl) implementa una inclusión diferente . – DwB

5

Tengo un pequeño problema, ¿hay alguna manera de incluir dinámicamente otro xsl? Por ejemplo:

<xsl:variable name="PathToWeb" select="'wewe'"/> 
<xsl:include href="http://{$PathToWeb}/html/xsl/head.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/navigation.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/promo.xsl" /> 
<xsl:include href="http://{$PathToWeb}/html/xsl/3columns.xsl" /> 

<xsl:include href="http://{$PathToWeb}/html/xsl/footer.xsl" /> 

Es ilegal tener una referencia variable en el atributo href de <xsl:include>. De acuerdo con las especificaciones W3C XSLT 1.0 y XSLT 2.0, el valor de este atributo debe ser una referencia URI.

Sin embargo, si el valor de la variable $PathToWeb se conoce antes del inicio de la transformación, que puede ser utilizado en un número de maneras de producir dinámicamente una representación hoja de estilo en el que los <xsl:include> declaraciones anteriormente contienen los URIs deseos (después de sustituir la referencia a $PathToWeb con el valor requerido:

  1. generar una nueva hoja de estilo de la actual, mediante XSLT

  2. carga. la hoja de estilos como un objeto XmlDocument. Luego ubique los elementos respectivos <xsl:include> y establezca sus atributos href en los valores deseados. Finalmente, invoque la transformación utilizando el XmlDocument modificado que representa la hoja de estilo.

2. Método ha sido utilizado durante 11 años en el XPath Visualizer para configurar dinámicamente el valor exacto de un atributo select utilizado para seleccionar todos los nodos que selecciona una expresión XPath introducida por el usuario y para generar un documento HTML representando el documento XML con todos los nodos seleccionados y visibles resaltados.

+1

He determinado empíricamente con XMLSpy que '' no permite una expresión XPath como el valor de su atributo 'href', mientras que' 'sí lo hace. Sin embargo, no puedo encontrar nada en la especificación que respalde esto. ¿Hay realmente una diferencia entre los dos, o es un error/una extensión patentada? (En realidad, ni siquiera estoy usando una variable, cualquier expresión como {'test'}.) – Dabbler

+1

No es un error. Los AVT están permitidos para el atributo 'href' de' 'con el propósito de permitir que se generen múltiples documentos de resultados. Hay una gran diferencia entre '' y ''. El primero solo se puede procesar en tiempo de compilación, este último se procesa en tiempo de ejecución. –

+3

No conozco muchos lenguajes de programación con construcciones que modifiquen el programa durante la ejecución, por lo que sería bastante sorprendente si se permitiera el uso de xsl: includes dinámicos. En cuanto a la especificación, la regla para xsl: include es '' mientras que para xsl: result-document es '

5

He resuelto este problema de manera diferente, podría ser útil para alguien que trabaja con Java y XSLT (esta solución es específica para personas que usan el paquete javax.xml.transform).

La fábrica de transformadores XSLT permite establecer una resolución de URI personalizada. Decir si su XSLT parece

<?xml version="1.0" encoding="utf-8"?> 
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="html" version="4.0" encoding="UTF-8"/> 
    <xsl:include href="import://stackoverflow.com/xsl"/> 
    ... 

método de la resolución de URI resolve obtendrá import://stackoverflow.com/xsl como parámetro href. import:// podría servir como un esquema identificador "especial" para inclusiones personalizadas, por lo que puede detectarlo y crear/devolver javax.xml.transform.Source que apunta al archivo necesario.Por ejemplo:

TransformerFactory tf = TransformerFactory.newInstance(); 
URIResolver delegate = tf.getURIResolver(); 
tf.setURIResolver(new CustomURIResolver(delegate)); 

Entonces, en el interior CustomURIResolver:

public Source resolve(String href, String base) 
    throws TransformerException { 
    Source result = null; 
    URI uri = null; 

    try { 
     uri = new URI(href); 
    } 
    catch(Exception e) { 
     throw new TransformerException(e); 
    } 

    // The XSLT file has a URI path that allows for a file to be included 
    // dynamically. 
    if("import".equalsIgnoreCase(uri.getScheme()) && 
     "stackoverflow.com".equalsIgnoreCase(uri.getAuthority())) { 
     result = openTemplate(); 
    } 
    else { 
     result = getDelegate().resolve(href, base); 
    } 

    return result; 
    } 

Añadir un método openTemplate() que incluye la lógica para determinar dinámicamente el archivo XSL para abrir.

0

En PHP, como en virtud de otros regímenes, es un proceso de múltiples pasos para usar una hoja de estilo XSL:

1) Crear un SimpleXML o un objeto DOMDocument de un archivo XSL.

2) Cree un objeto XSLTProcessor.

3) Importe el objeto del documento XSL en el objeto del procesador.

4) Ejecute una transformación en un archivo de datos XML.

Después de 1), el XSL se puede manipular antes de compilarse como parte del paso 3). Es aquí donde los elementos xsl: include pueden insertarse dinámicamente desde el elemento raíz según sea necesario.

Por lo tanto, para insertar dinámicamente XSL: incluye:

1.1) Uso Xpath | getElemenById | GetElementsByTagName para examinar el XML de datos para la existencia de elementos para los que podría requerir hojas de estilo adicionales.

1.2) Cree dinámicamente xsl: incluya elementos fuera del elemento raíz del objeto XML de XSL.

Eso es todo. En el paso 3), el objeto XML XSL modificado se compilará como si estuviera construido de esa manera desde el principio.

Por supuesto, en 1.2), CUALQUIER nodo (no solo xsl: include o xsl: import) de otros objetos de documento XSL puede agregarse CUALQUIER nodo en el objeto de documento base XSL, proporcionando un control mucho más preciso. Sin embargo, la construcción correcta de xsl: template de todas las hojas de estilo XSL debería hacer que sea mucho más sencillo insertar elementos xsl: include.

0

Mis 2 peniques por valor en una alternativa simple (pero efectivo) (sólo psuedocode proporcionan para ilustración de proceder con cautela :)

Esquema del enfoque:. Una solución alternativa puede consistir en un simple script envoltorio (por ejemplo, shell, bash script u otro) para invocar a su xsl principal, uso de los modos xslt de nombre, el archivo xslt principal, un archivo xslt especificado de forma estática (en blanco).

En la xsl principal, incluya un archivo xsl estático, que invocará/cargará todo el xslt incluido dinámicamente. El xsl principal operará en 2 modos: el modo normal (modo no especificado), donde cargará los archivos de extensión xsl incluidos en sí mismo, y en los archivos xls estáticos, y procesará los archivos de entrada, o hará lo que sea bueno para su propósito. hacer. El segundo modo, modo de preprocesador, estará destinado a cargar las instancias/archivos xsl especificados dinámicamente. Este modo se invocará como una etapa de preprocesador para la ejecución de procesamiento principal. El flujo de proceso para el xslt principal sería llamarlo con el modo de preprocesador especificado, y luego volver a llamarlo con el modo de procesamiento normal indicado.

Indicaciones de implementación: Para cada xlator defina una extensión n archivo xslt, ext_xsl_container, cuyo propósito es incluir cualquier extensión xslt. por ejemplo, hoja de estilo

<xsl:stylesheet > 
    <!-- main xslt --> 
     <xsl:import href="../xsl/ext_xsl_container.xsl/> 
     <!--param: list of dynamically specified extension xsl --> 
     <xsl:param name="extXslUrlList"/> 
     <!--param:preprocessor mode flag, with default set to false --> 
     <xsl:param name="preProcModeLoadXslF" select="false()" type="xs:boolean" 
<!-- param: path to the staticall included ext_xsl_container: with default value set --> 
    <xsl:param name="extXslContainerUrl" select="'../xsl/ext_xsl_container.xsl'"/> 

     <xsl:if test=" ($preProcModeLoadXslF=true())" > 
      <xsl:call-template name="loadDynamicXsl" mode="preprocess_load_xsl" 
     </xsl:if> 
     .... 
    </xsl:stylesheet> 

El ext_xslt_container incluirá cualquier XSLT de extensión. Se puede actualizar dinámicamente en tiempo de ejecución editándolo (como un documento xml) y agregando una instrucción include para la extensión xsl stylesheets. por ejemplo

<!-- ext xsl container : ext_xsl_container.xsl--> 
<xsl:stylesheet 
    <xsl:include href="ext_xsl_container.xsl"/> 

    .... 
</xsl:stylesheet 

Crear una plantilla pequeña, digamos template_load_ext_xsl, con un modo asignado, por ejemplo mode = "preprocess_load_xsl" por ejemplo

<xsl:template name="loadDynamicXsl" mode="preprocess_load_xsl"> 
    <!-- param: path to the staticall included ext_xsl_container--> 
    <xsl:param name="extXslContainerUrl"/> 
    <!--param: list of dynamically specified extension xsl --> 
    <xsl:param name="extXslUrlList"/> 

    <!-- step 1, [optional ] open the ext Xsl container file --> 
    <!-- step 2 [optional] clear contexts of the ext X -- > 
    <!-- step3 compile a list of include elements, one per each ext Xsl file --> 
    <!-- step 4 [optional] create a union of the include elements created with the content of the xsl container file : ie append content > 
<!-- step 5 : write the union list of incudes to the ext XSL container file --> 
<!-- DONE ---> 

</xsl:template> 

La plantilla tomará como argumentos, el nombre de la ex_xsl_container, y una lista de archivos xsl de extensión (incluyendo sus rutas) , luego abrirá el archivo ext_xsl_container como un documento xml, agregará (opciones para agregar, o borrará archivos y agregará código nuevo) instrucciones para cada extensión: xsl, guarde el archivo y salida

siguiente cuando se ejecuta el XSL principal en el modo de ejecución normal, que willl incluye el loadDynamicXsl plantilla, que inturn incluirá los archivos de extensión de XSLT specifed en tiempo de ejecución

Crear un script sencillo envoltorio (por ejemplo, golpe o shell script) que incluirá argumentos en el xslt principal y una opción para ejecutar el modo de preprocesador. La secuencia de comandos simplemente llamará a la xslt principal dos veces, si la opción para el modo de preprocesador está habilitada y habilitando el modo de preprocesador en la primera ejecución, seguido de una segunda llamada en modo normal

Cuestiones relacionadas