(Ответ расширен для обработки передачи проанализированного документа DOM W3C через URIResolver)
Это можно сделать в чистом XSLT / XPath с использованием версии Xalan XSLT-процессора, которая являетсяпоставляется с JRE.
В качестве примера, скажем, если имя одного из входных документов передается в качестве параметра в Transformer
:
File parentDir = new File("c:\\dir");
StringWriter stringWriter = new StringWriter();
File xml = new File(parentDir, "input.xml");
File xsl = new File(parentDir, "xslt-document-param.xslt");
Source xsltSource = new StreamSource(xsl);
Source xmlSource = new StreamSource(xml);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer(xsltSource);
transformer.setParameter("doc-name", "basic.xml");
transformer.transform(xmlSource, new StreamResult(stringWriter));
System.out.println(stringWriter);
Этот параметр может затемпередается в функцию document()
в XPath следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://xml.apache.org/xalan"
version="1.0"
exclude-result-prefixes="xalan">
<xsl:output
method="xml"
indent="yes"
xalan:indent-amount="2"/>
<xsl:param name="doc-name"/>
<xsl:template match="/">
<xsl:variable name="doc-content" select="document($doc-name)"/>
<parent>
<xsl:for-each select="$doc-content/basic/*">
<child>
<xsl:value-of select="name(.)"/>
</child>
</xsl:for-each>
</parent>
</xsl:template>
</xsl:stylesheet>
Это может прочитать basic.xml
(из параметра):
<basic>
<one/>
<two/>
<three/>
</basic>
и преобразовать его в:
<parent>
<child>one</child>
<child>two</child>
<child>three</child>
</parent>
Параметром для функции document()
является URI.Относительный путь разрешается относительно файла XSL.В равной степени это может быть полный URL-адрес или разрешено с помощью пользовательского transformer.setURIResolver()
, как в вопросе.
(редактировать отсюда ...)
Для работы сПередача предварительно проанализированного объекта Document
в XSLT, подход URIResolver
может обработать передачу этого обратно функции document()
.
Например, с поиском в вопросе:
File lookupXml = new File(parentDir, "basic.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(lookupXml);
Map<String, Document> docs = new HashMap<>();
docs.put("lookup", document);
transformer.setURIResolver((href, base) -> new DOMSource(docs.get(href)));
Этот XSL может выполнять итерацию того же basic.xml
, как указано выше ...
<xsl:template match="/">
<xsl:variable name="doc-content" select="document('lookup')"/>
<parent>
<xsl:for-each select="$doc-content/basic/*">
<child>
<xsl:value-of select="name(.)"/>
</child>
</xsl:for-each>
</parent>
</xsl:template>
... и выводить тот же результат.