2010-08-18 19 views
5

La respuesta más común a esta pregunta describe una técnica para poner en práctica una tubería XSLT eficiente en Java:tubería XSLT eficiente, con parametros, en Java

Efficient XSLT pipeline in Java (or redirecting Results to Sources)

Lamentablemente, si bien Transformador parece exponer una API para establecer Parámetros XSLT, esto no parece tener ningún efecto. Por ejemplo, tengo el siguiente código:

Transformer.java

import javax.xml.transform.sax.SAXTransformerFactory; 
import javax.xml.transform.Templates; 
import javax.xml.transform.sax.TransformerHandler; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.stream.StreamResult; 
import javax.xml.transform.stream.StreamSource; 
import javax.xml.transform.sax.SAXResult; 
import javax.xml.transform.Transformer; 
import java.io.File; 
public class MyTransformer { 
    public static void main(String[] args) throws javax.xml.transform.TransformerConfigurationException, javax.xml.transform.TransformerException{ 
     SAXTransformerFactory stf = (SAXTransformerFactory)TransformerFactory.newInstance(); 

     // These templates objects could be reused and obtained from elsewhere. 
     Templates templates1 = stf.newTemplates(new StreamSource(new File("MyStylesheet1.xslt"))); 
     Templates templates2 = stf.newTemplates(new StreamSource(new File("MyStylesheet2.xslt"))); 

     TransformerHandler th1 = stf.newTransformerHandler(templates1); 
     TransformerHandler th2 = stf.newTransformerHandler(templates2); 

     th1.setResult(new SAXResult(th2)); 
     th2.setResult(new StreamResult(System.out)); 

     Transformer t = stf.newTransformer(); 

      //SETTING PARAMETERS HERE 
     t.setParameter("foo","this is from param 1"); 
     t.setParameter("bar","this is from param 2"); 

     t.transform(new StreamSource(new File("in.xml")), new SAXResult(th1)); 

     // th1 feeds th2, which in turn feeds System.out. 
    } 
} 

MyStylesheet1.xslt

<?xml version="1.0"?> 
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:foo="urn:foo" version="1.0"> 
    <output method="xml"/> 

    <param name="foo"/> 

    <template match="@*|node()"> 
     <copy> 
      <apply-templates select="@*|node()"/> 
     </copy> 
    </template> 

    <template match="foo:my/foo:hello"> 
     <copy> 
      <foo:world> 
       foo is : <value-of select="$foo"/> 
      </foo:world> 
     </copy> 

    </template> 
</stylesheet> 

MyStylesheet2.xslt

<?xml version="1.0"?> 
<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" xmlns:foo="urn:foo" version="1.0"> 
    <output method="xml"/> 

    <param name="bar"/> 

    <template match="@*|node()"> 
     <copy> 
      <apply-templates select="@*|node()"/> 
     </copy> 
    </template> 

    <template match="foo:my/foo:hello/foo:world"> 
     <copy> 
      <apply-templates select="@*|node()"/> 

      <attribute name="attr"> 
       <value-of select="$bar"/> 
      </attribute> 
     </copy> 

    </template> 
</stylesheet> 

in.xml

<my xmlns="urn:foo"> 
    <hello/> 
</my> 

Lo que me da el siguiente resultado:

<?xml version="1.0" encoding="UTF-8"?><my xmlns="urn:foo"> 
     <hello><foo:world xmlns:foo="urn:foo">foo is : </foo:world></hello> 
</my> 

Como se puede ver foo: El Mundo/@ attr está vacía, y los contenidos de texto de foo: mundo dice "foo es:". El comportamiento esperado es que deberían haberse completado con los parámetros pasados ​​al método setParameter.

Hay una manera de establecer los parámetros de transformación XSL utilizando esta técnica. Si no, ¿alguien podría recomendar una técnica alternativa para transformar las hojas de estilo de manera eficiente en Java, de modo que los parámetros XSLT también puedan establecerse?

Respuesta

6

El problema es que cada TransformerHandler tiene asociado un transformador por separado. Hay un problema con su segunda plantilla, pero como este es un ejemplo, supongo que eso no importa. ¿Quieres:

//SETTING PARAMETERS HERE 
th1.getTransformer().setParameter("foo","this is from param 1"); 
th2.getTransformer().setParameter("bar","this is from param 2"); 

en cuenta que también no es necesario crear una tercera transformador se puede simplemente comenzar la cadena de transformación en th1.getTransformer()

0

relacionada con la última nota. invocando transform() en th1.getTransformer() con el resultado apuntando nuevamente en th1 no es correcto. Se procesará dos veces. usando el nuevo transformador() como se muestra en la publicación inicial es la forma correcta.

t.transform(new StreamSource(new File("in.xml")), new SAXResult(th1)); 
Cuestiones relacionadas