2010-08-18 7 views
5

La top réponse à cette question décrit une technique pour la mise en œuvre d'un pipeline XSLT efficace en Java:pipeline XSLT efficace, avec params, en Java

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

Malheureusement, alors que Transformer semble exposer une API pour la mise en Paramètres XSLT, cela ne semble pas avoir d'effet. Par exemple, j'ai le code suivant:

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> 

Ce qui me donne le résultat suivant:

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

Comme vous pouvez le voir foo: world/@ attr est vide, et le contenu du texte de foo: monde dit "foo est:". Le comportement attendu est qu'ils devraient avoir été remplis avec les paramètres passés dans la méthode setParameter.

Y at-il un moyen de définir les paramètres de transformation XSL en utilisant cette technique. Si non, quelqu'un pourrait-il recommander une technique alternative pour transformer efficacement les feuilles de style en Java, de sorte que les paramètres XSLT puissent également être définis?

Répondre

6

Le problème est que chaque TransformerHandler est associé à un Transformer distinct. Il y a un problème avec votre 2ème modèle, mais comme c'est un exemple je suppose que cela n'a pas d'importance. Vous voulez:

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

Notez que vous n'avez pas besoin de créer un 3ème transformateur, vous pouvez commencer la transformation sur la chaîne th1.getTransformer()

0

liée à la dernière note. invoquer transform() sur th1.getTransformer() avec le résultat pointant à nouveau sur th1 n'est pas correct. Il sera traité deux fois. en utilisant le nouveau Transformer() comme indiqué dans la publication initiale est la bonne façon.

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