Wenn Sie Artefakte in einen J2EE-Kontext (Java™ 2
Platform, Enterprise Edition) laden, müssen Sie auf Implikationen achten, die sich beim Laden von Ressourcen aus lokalen Implementierungsartefakten
ergeben können.
Informationen zu diesem Vorgang
Wenn Sie lokale Ressourcen mit Class.getResource und
Class.getResourceAsStream aus J2EE-Implementierungsartefakten laden, z. B. aus EAR-Dateien, WAR-Dateien
oder Bibliotheks-JAR-Dateien, können beim Laden zugehöriger XML-Artefakte Probleme auftauchen. Das Laden einer lokalen Ausgangsressource mit diesen Mechanismen wird gelingen.
Artefakte, die aus der Ausgangsressource geladen werden, können jedoch nur unter Berücksichtigung bestimmter
Aspekte erfolgreich geladen werden.
Im folgenden Beispiel werden in der Ausführungszeit Dokumente mit der XPath-Funktion
fn:doc aus einem Style-Sheet geladen. Dokumente werden in diesem Fall standardmäßig anhand des Basis-URI
aus dem statischen Kontext aufgelöst.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="names" select="doc('names.xml')"/>
<xsl:template name="loadnames">
<xsl:copy-of select="$names"/>
</xsl:template>
</xsl:stylesheet>
Wenn die Dokumente mit dem folgenden
Java-Code in einer J2EE-Umgebung geladen werden, sieht das Beispiel wie folgt aus:
// Factory erstellen
XFactory factory = XFactory.newInstance();
// XSLT-Datei aus einer lokalen Ressource innerhalb eines J2EE-Implementierungsartefakts laden
StreamSource source = new StreamSource(XSLTDocFunction.class.getResourceAsStream("/samplexslts/doc.xsl"));
// Ausführbares Objekt für XSL-Transformation erstellen
XSLTExecutable xslTransform = factory.prepareXSLT(source);
// Ergebnis erstellen
Result result = new StreamResult(new ByteArrayOutputStream());
// Dynamischen Kontext durch Angabe einer XSLT-Anfangsschablone erstellen
XDynamicContext dc = factory.newDynamicContext();
dc.setXSLTInitialTemplate(new QName("loadnames"));
// Transformation durchführen
xslTransform.execute(dc, result);
Sie empfangen den folgenden Fehler:
IXJXE0364W: FATAL ERROR: IXJXE0774E: [ERR 0693][ERR FODC0005]
The URI string 'names.xml' does not map to an available document.
Dieser Fehler tritt auf,
weil beim Laden des ersten XML-Artefakts
(doc.xsl) kein statischer Kontext für den Basis-URI eingerichtet war. Der Prozessor greift in dem Fall auf
die Suche im aktuellen Arbeitsverzeichnis zurück, die in einer
J2EE-Umgebung keinen Sinn macht.
In dieser Situation haben Sie drei Möglichkeiten, Abhilfe zu schaffen. Hier sind die beiden ersten angegeben:
- Setzen Sie den Basis-URI im statischen Kontext.
Zum Setzen des Basis-URI im statischen Kontext müssten Sie eine Anpassung
wie im folgenden Beispiel vornehmen:
// Factory erstellen
XFactory factory = XFactory.newInstance();
// Basis-URI im statischen Kontext festlegen
URL dataURL = XSLTSchemaAware.class.getResource("/samplexslts/doc.xsl");
XStaticContext staticContext = factory.newStaticContext();
staticContext.setBaseURI(dataURL.toString());
// XSLT-Datei aus einer lokalen Ressource innerhalb eines J2EE-Implementierungsartefakts laden
StreamSource source = new StreamSource(XSLTDocFunction.class.getResourceAsStream("/samplexslts/doc.xsl"));
// Ausführbares Objekt für XSL-Transformation erstellen
XSLTExecutable xslTransform = factory.prepareXSLT(source, staticContext);
// Ergebnis erstellen
Result result = new StreamResult(new ByteArrayOutputStream());
// Dynamischen Kontext durch Angabe einer XSLT-Anfangsschablone erstellen
XDynamicContext dc = factory.newDynamicContext();
dc.setXSLTInitialTemplate(new QName("loadnames"));
// Transformation durchführen
xslTransform.execute(dc, result);
- Laden Sie die Ressource so, dass der Prozessor den Basis-URI kennt.
Um die Ressource so zu laden, dass der Prozessor den Basis-URI kennt, müssen Sie wie im folgenden Beispiel
den absoluten URI an den Konstruktor StreamSource übergeben:
// Factory erstellen
XFactory factory = XFactory.newInstance();
// Quelle aus einem URL erstellen
URL dataURL = XSLTSchemaAware.class.getResource("/samplexslts/doc.xsl");
StreamSource source = new StreamSource(dataURL.toString());
// Ausführbares Objekt für die XSL-Transformation für den Ausdruck erstellen
XSLTExecutable xslTransform = factory.prepareXSLT(source);
// Ergebnis erstellen
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Result result = new StreamResult(baos);
// Dynamischen Kontext durch Angabe einer XSLT-Anfangsschablone erstellen
XDynamicContext dc = factory.newDynamicContext();
dc.setXSLTInitialTemplate(new QName("loadnames"));
// Transformation durchführen
xslTransform.execute(dc, result);
Diese beiden Strategien sind erfolgversprechend, wenn sich alle XML-Artefakte
in derselben J2EE-Implementierungseinheit befinden. Sie bringen jedoch nicht den gewünschten Erfolg, wenn XML-Artefakte
auf mehrere J2EE-Implementierungseinheiten verteilt sind, weil es keinen einheitlichen Basis-URI für alle XML-Artefakte
gibt.
Verwenden Sie für eine vollständige Kontrolle über das Ladeverhalten Resolver, die das Laden von XML-Artefakten auch dann unterstützen, wenn
Artefakte auf mehrere Implementierungseinheiten verteilt sind.
Implementieren Sie die geeigneten Resolver und registrieren Sie sie im statischen bzw. im dynamischen Kontext. Diese Empfehlungen für das Laden von
XML-Artefakten gelten für alle XML-Artefakte in einem J2EE-Kontext, die von Resolvern unterstützt werden, z. B.
von Resolvern für XML-Dokumente (fn:doc(),
document()), für Style-Sheets (xsl:include, xsl:import), für nicht analysierten Text und
für XML-Schemata (XSLT import-schema).