2010-08-18 50 views
5

顶端回答这个问题介绍了一种技术,在Java中实现高效的XSLT管道:高效XSLT管道,使用参数,在Java

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

不幸的是,当变压器似乎暴露了一个API设置XSLT参数,这似乎没有任何影响。例如,我有以下代码:

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> 

这给了我下面的输出:

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

正如你可以看到富:世界/ @ attr为空,foo的文本内容:大家说: “foo是:”。预期的行为是应该使用传递给setParameter方法的参数填充它们。

有没有办法使用这种技术设置XSL转换参数。如果没有,任何人都可以推荐一种替代技术来在Java中高效地转换样式表,这样XSLT参数也可以被设置?

回答

6

问题是每个TransformerHandler都有一个独立的变压器与之相关联。你的第二个模板存在问题,但是这是一个例子,我想这并不重要。你想:

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

注意,你也不需要创建一个第三变压器你可以开始th1.getTransformer变换链()

0

相关的最后一个音符。 在th1.getTransformer()上调用transform()时,再次在th1上指向的结果不正确。它将被处理两次。 使用新的Transformer()如初始文章所示是正确的方法。

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