如何使用Javax.xml.transformer API将XML文档传递给XSL文件?

Cha*_*abh 6 java xml transformation xslt-2.0

我正在使用javax.xml.transformAPI来进行XSL转换.API仅允许一个XML文档作为输入应用转换,如下所示.

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    StringWriter stringWriter = new StringWriter();
    File xml = new File("C:\\abc");
    File xsl = new File("C:\\def.xsl");
    factory.setNamespaceAware(true);
    DocumentBuilder builder = factory.newDocumentBuilder();
    document = builder.parse(xml);
    TransformerFactory transformerFactory = 
    TransformerFactory.newInstance();
    StreamSource style = new StreamSource(xsl);
    Transformer transformer = transformerFactory.newTransformer(style);
    DOMSource source = new DOMSource(document);
Run Code Online (Sandbox Code Playgroud)

此外,可以传递简单的字符串参数,如下所示,没有任何问题如下:

transformer.setParameter("mode", "CREATE");
Run Code Online (Sandbox Code Playgroud)

但是,我想将XML Document作为参数传递给XSL文件.我按照SO页面上的建议尝试了下面的代码,如下所示:

DocumentBuilder builder = factory.newDocumentBuilder();
 final Document documentFile = builder.parse(xml2);
 Map<String, Document> docs = new HashMap<String, Document>();
 docs.put("lookup", documentFile);
 transformer.setURIResolver(new DocumentURIResolver(docs));
Run Code Online (Sandbox Code Playgroud)

我设置,XML中的标记接收值如下:

<xsl:variable name="lookup" select="('documentFile')/>  . 
Run Code Online (Sandbox Code Playgroud)

但它不适合我.任何人都可以帮助我通过javax.xml.transform API将多个XML文档传递给任何XSL文件吗?

更新

仍然坚持这个问题,任何人都可以让我如何将XML对象作为参数传递给XSLT 2.0样式表.我尝试了不同的方法,但仍然没有运气.我需要通过JAVA xsl转换API了解一条出路.

jsc*_*sse 3

我认为你的问题出在 XSLT 上。改变

<xsl:variable name="lookup" select="('documentFile')/>  . 
Run Code Online (Sandbox Code Playgroud)

到

<xsl:variable name="lookup" select="document('lookup')/>
Run Code Online (Sandbox Code Playgroud)

这将导致转换器使DOM您的文档的 可以在变量中访问lookup。关键lookup来自docs.put("lookup", documentFile);

通过 URIResolver 动态地将多个 XML 源传递到 XSL 转换。

完整的工作示例:

存在三个 XML 文件:repo.xml、books.xml和articles.xml. 包含repo.xml有关书籍和文章的状态信息。这些文件articles.xml包含books.xml有关每个项目的标题信息。目标是打印所有书籍和文章的状态信息以及标题信息。所有文件中的条目都通过id键连接。

在github上查找完整示例或复制/粘贴下面的列表。

仓库.xml

<repository>
    <book>
        <id>1</id>
        <status>available</status>
    </book>
    <book>
        <id>2</id>
        <status>lost</status>
    </book>
    <article>
        <id>1</id>
        <status>in transit</status>
    </article>
</repository>
Run Code Online (Sandbox Code Playgroud)

书籍.xml

<books>
    <book id="1">
        <title>Book One</title>
    </book>
    <book id="2">
        <title>Book Two</title>
    </book>
    <book id="3">
        <title>Book Three</title>
    </book>
</books>
Run Code Online (Sandbox Code Playgroud)

文章.xml

<articles>
    <article id="1">
         <title>Article One</title>
    </article>
    <article id="2">
        <title>Article Two</title>
    </article>
    <article id="3">
        <title>Article Three</title>
    </article>
</articles>
Run Code Online (Sandbox Code Playgroud)

加入.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">


<xsl:output method="xml" encoding="UTF-8" indent="yes" />

<xsl:template match="/">
    <titleStatusJoin>
        <xsl:for-each select="//book">
            <xsl:variable name="myId" select="id" />
            <book>
                <status>
                    <xsl:value-of select="status" />
                </status>
                <title>
                    <xsl:for-each select="document('bookFile')//book">
                        <xsl:variable name="bookId" select="@id" />
                        <xsl:choose>
                            <xsl:when test="$myId = $bookId">
                                <xsl:value-of select="title" />
                            </xsl:when>
                        </xsl:choose>
                    </xsl:for-each>
                </title>
            </book>
        </xsl:for-each>
        <xsl:for-each select="//article">
            <xsl:variable name="myId" select="id" />
            <article>
                <status>
                    <xsl:value-of select="status" />
                </status>
                <title>
                    <xsl:for-each select="document('articleFile')//article">
                        <xsl:variable name="bookId" select="@id" />
                        <xsl:choose>
                            <xsl:when test="$myId = $bookId">
                                <xsl:value-of select="title" />
                            </xsl:when>
                        </xsl:choose>
                    </xsl:for-each>
                </title>
            </article>
        </xsl:for-each>

    </titleStatusJoin>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

使用这个Java代码...

@Test
public void useMultipleXmlSourcesInOneXsl3() {
    InputStream xml = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/repo.xml");
    InputStream xsl = Thread.currentThread().getContextClassLoader().getResourceAsStream("stack54335576/join3.xsl");
    InputStream booksXml = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("stack54335576/books.xml");
    InputStream articlesXml = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("stack54335576/articles.xml");
    Document booksDom = readXml(booksXml);
    Document articlesDom = readXml(articlesXml);
    Map<String, Document> parameters = new HashMap<>();
    parameters.put("bookFile", booksDom);
    parameters.put("articleFile", articlesDom);
    xslt(xml, xsl, parameters);
}

public final void xslt(InputStream xml, InputStream xsl, Map<String, Document> parameters) {
    try {
        TransformerFactory factory = TransformerFactory.newInstance();
        Transformer transformer = factory.newTransformer(new StreamSource(xsl));
        transformer.setURIResolver((href, base) -> new DOMSource(parameters.get(href)));
        transformer.transform(new StreamSource(xml), new StreamResult(System.out));
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

private Document readXml(InputStream xmlin) {
    try {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        return db.parse(xmlin);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Run Code Online (Sandbox Code Playgroud)

...产生这个输出

<?xml version="1.0" encoding="UTF-8"?>
<titleStatusJoin>
   <book>
      <status>available</status>
      <title>Book One</title>
   </book>
   <book>
     <status>lost</status>
     <title>Book Two</title>
   </book>
   <article>
     <status>in transit</status>
     <title>Article One</title>
   </article>
</titleStatusJoin>
Run Code Online (Sandbox Code Playgroud)