2011-11-13 101 views
1


我目前正在使用XSL-Transformations從XML生成HTML的項目。 在輸入字段有一些屬性,我必須設置。
樣品:XSL的後處理步驟

<input name="/my/xpath/to/node" 
     class="{/my/xpath/to/node/@isValid}" 
     value="{/my/xpath/to/node}" /> 

這是非常愚蠢的,因爲我有寫相同的XPath 3次......我的想法是有某種後處理器的XSL文件,所以我可以這樣寫:

<input xpath="/my/xpath/to/node" /> 

我使用的是類似的東西進行改造我的XML

import javax.xml.transform.Transformer; 
import javax.xml.transform.TransformerFactory; 

import org.dom4j.Document; 
import org.dom4j.io.DocumentResult; 
import org.dom4j.io.DocumentSource; 

public class Foo { 

    public Document styleDocument(
     Document document, 
     String stylesheet 
    ) throws Exception { 

     // load the transformer using JAXP 
     TransformerFactory factory = TransformerFactory.newInstance(); 
     Transformer transformer = factory.newTransformer( 
      new StreamSource(stylesheet) 
     ); 

     // now lets style the given document 
     DocumentSource source = new DocumentSource(document); 
     DocumentResult result = new DocumentResult(); 
     transformer.transform(source, result); 

     // return the transformed document 
     Document transformedDoc = result.getDocument(); 
     return transformedDoc; 
    } 
} 

我希望利用的是,我可以出一個Document對象的創建Transformer對象。但它似乎必須是一個文件路徑 - 至少我找不到直接使用文檔的方法。
任何人都知道一種方法來實現我想要的?

感謝

回答

0

我的希望是我可以從Document對象中創建一個Transformer對象。但它似乎必須是一個文件路徑 - 至少我找不到直接使用文檔的方法。

您可以從文檔對象創建Transformer對象:

Document stylesheetDoc = loadStylesheetDoc(stylesheet); 
    // load the transformer using JAXP 
    TransformerFactory factory = TransformerFactory.newInstance(); 
    Transformer transformer = factory.newTransformer( 
     new DOMSource(stylesheetDoc) 
    ); 

實施loadStylesheetDoc留下作爲一個鍛鍊; Tibial。您可以在內部構建樣式表Document或使用jaxp加載它,甚至可以將需要的更改作爲另一個XSLT轉換來轉換樣式表。

+0

它看起來像包括可以通過實現一個自定義的URIResolver(factory.setURIResolver(...))來解決 – Daniel

2

爲什麼不跳過後處理,並在XSLT使用:

<xsl:variable name="myNode" select="/my/xpath/to/node" /> 

<input name="/my/xpath/to/node" 
    class="{$myNode/@isValid}" 
    value="{$myNode}" /> 

這讓你更接近。

如果你真的想幹DRY(你顯然是這麼做的),甚至可以使用變量myNodePath,通過模板或用戶定義的函數爲其生成$ myNode的值。這個名字真的是一個XPath表達式

更新(而不是一個generate-id()):

示例代碼:

<xsl:variable name="myNode" select="/my/xpath/to/node" /> 
<xsl:variable name="myNodeName"> 
    <xsl:apply-template mode="generate-xpath" select="$myNode" /> 
</xsl:variable> 

<input name="{$myNodeName}" 
    class="{$myNode/@isValid}" 
    value="{$myNode}" /> 

generate-xpath模式的模板可在網絡上...例如,您可以使用Schematron附帶的模板之一。請轉至this page,下載iso-schematron-xslt1.zip,然後查看iso_schematron_skeleton_for_xslt1.xsl。 (如果您能夠使用XSLT 2.0,請下載該zip壓縮文件。)

在那裏您會找到幾個schematron-select-full-path的實現,您可以使用它們來執行generate-xpath。一個版本是精確的,最適合程序使用;另一個更具有人類可讀性。請記住,對於XML文檔中的任何給定節點,都有大量的XPath表達式可用於僅選擇該節點。所以你可能不會得到與你一開始就使用的XPath表達式。如果這是一個交易斷路器,你可能想嘗試另一種方法,比如...

用另一個XSLT樣式表生成你的XSLT樣式表(你已經開發的那個,稱之爲A) B)。當B生成A時,B有機會將XPath表達式輸出爲帶引號的字符串,並作爲將被評估的表達式。這基本上是在XSLT中預處理而不是在Java中進行後處理。我不確定它是否適用於你的情況。如果我知道輸入的XML是什麼樣子的話,那麼弄清楚我的想法會更容易。

+0

是的名稱必須是xpath。問題是寫入xsl文件的人會忘記一個屬性。我想盡可能地減少錯誤傾向性。你能給我一個你的其他解決方案的例子(但我想代碼將不再像「普通」的HTML?) – Daniel

+0

@Daniel,我更新了我的答案以迴應您的要求。 – LarsH