在java中从String处理XSLT Source时,使用键进行XSLT查找

时间:2011-06-15 10:08:14

标签: xslt

我正在尝试处理XSLT查找 - 在某些修改后将输入XSLT作为String而不是文件。如果我将修改后的XSLT作为文件编写并再次读取以进行转换,但是当我将其作为字符串处理时,查找功能将无效。

进行转换的方法如下。

    public static void transform(File inputXmlfile, String outputXmlFileName) throws ParserConfigurationException, SAXException, IOException, TransformerException {

    DocumentBuilderFactory docBuildFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder parser = docBuildFactory.newDocumentBuilder();
    Document document = parser.parse(inputXmlfile);

    TransformerFactory xformFactory = TransformerFactory.newInstance();

    String xsltString="<?xml version=\"1.0\" encoding=\"utf-8\"?>"+
    "<xsl:stylesheet version=\"1.0\""+
    " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" xmlns:c=\"http://myDomain.com/classifications.data\">"+
    "<xsl:output method=\"xml\" />"+
    "<xsl:key name=\"classification-lookup\" match=\"c:classification\" use=\"c:id\" /> <xsl:template match=\"/\"><listings xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://local.google.com/local_feed.xsd\"><language>en</language><datum>WGS84</datum>" +
    "<xsl:for-each select=\"BusinessListings/BusinessListing\"><listing><id><xsl:value-of select=\"id\" /></id><xsl:apply-templates /></listing></xsl:for-each></listings></xsl:template><xsl:template match=\"classificationId\"><xsl:variable name=\"currentId\" select=\".\" />" +
    "<xsl:for-each select=\"document('')\"><category><xsl:value-of select=\"key('classification-lookup',$currentId)/c:description\" /></category></xsl:for-each></xsl:template> <xsl:template match=\"text()\" />" +
    "<c:classifications><c:classification><c:id>3</c:id><c:description>Abortion Alternatives</c:description></c:classification><c:classification><c:id>4</c:id><c:description>Abortion Providers</c:description>" +
    "</c:classification><c:classification><c:id>9</c:id><c:description>Abrasives</c:description></c:classification></c:classifications></xsl:stylesheet>";

    Transformer transformer = xformFactory.newTransformer(new StreamSource(IOUtils.toInputStream(xsltString)));
    transformer.setOutputProperty(OutputKeys.INDENT, "yes");

    FileOutputStream fileOutputStream = new FileOutputStream(new File(outputXmlFileName));  
    DOMSource source = new DOMSource(document);
    Result result = new StreamResult(fileOutputStream);
    transformer.transform(source, result);

    fileOutputStream.close();

}

当我尝试如下(在编写modifiel xsl并将其读回之后)

    Transformer transformer = xformFactory.newTransformer(new StreamSource(xsltFile));

它工作正常 - 但

    Transformer transformer = xformFactory.newTransformer(new StreamSource(IOUtils.toInputStream(xsltString))); does not process the lookup.

输入如下

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BusinessListings vendorId="0" schemaVersion=""
fileCreateDate="" xmlns="http://www.myDomain.com">
<BusinessListing>
    <id>1593469</id>
    <listingData>
        <classifications>
            <classificationId>3</classificationId>
            <classificationId>9</classificationId>
        </classifications>
    </listingData>
</BusinessListing>
</BusinessListings>

问题是什么?

2 个答案:

答案 0 :(得分:0)

您可以将ByteArrayInputStream传递给StreamSource对象吗?您可以使用String初始化它。

类似的东西:

ByteArrayInputStream bais = new ByteArrayInputStream(xsltString.getBytes(), "UTF-8");
Transformer transformer = xformFactory.newTransformer( new StreamSource( bais ) );

答案 1 :(得分:0)

首先,回答您的问题 - 请参阅XSLT 1.0规范,该规范解释了document function使用零长度字符串arg:

  

请注意,零长度URI引用是对文档的引用,相对于该文档,URI引用正在被解析;因此,文档(“”)指的是样式表的根节点;样式表的树表示与包含样式表的XML文档是初始源文档完全相同。

由于样式表的源是内存中的流,因此没有可用于解析它的URI。它适用于文件,因为它能够解析文件的位置并重新加载它。可能有一些方法可以使用系统ID或自定义URI解析器,但我认为这可能是一种更简单的方法。

其次,为什么要在XSLT中嵌入分类数据?为什么不把它作为一个参数传递给它?它似乎更容易,并且通过使用对参数的引用替换文档('')调用将大致相同。