2010-08-18 48 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));