XSL的后处理步骤

时间:2011-11-13 12:27:47

标签: java xslt dom4j


我目前正在开发一个使用XSL-Transformations从XML生成HTML的项目。 在输入字段中,我必须设置一些属性。
样品:

<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对象。但它似乎必须是一个文件路径 - 至少我找不到直接使用Document的方法。
谁知道实现我想要的方法?

感谢

2 个答案:

答案 0 :(得分:2)

为什么不跳过后处理,并在XSLT中使用它:

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

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

让你更接近。

如果你真的想要干(显然你做),你甚至可以使用变量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样式表(称之为B)生成您的XSLT样式表(您已经开发的样式表,称之为A)。当B生成A时,B有机会将XPath表达式作为带引号的字符串输出,并作为将要计算的表达式。这基本上是在XSLT中进行预处理,而不是在Java中进行后处理。我不确定它是否适用于您的情况。如果我知道输入XML是什么样的,那么我认为更容易理解。

答案 1 :(得分:0)

  

我希望我能用Document对象创建一个Transformer对象。但它似乎必须是一个文件路径 - 至少我找不到直接使用Document的方法。

您可以从文档对象创建Transformer对象:

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

实施loadStylesheetDoc作为练习。您可以在内部构建样式表Document或使用jaxp加载它,您甚至可以将所需的更改写为另一个XSLT转换变换样式表所需的更改。