J'utilise l'API javax.xml.transform
pour effectuer une transformation XSL. L'API n'autorise qu'un seul document XML comme entrée pour appliquer la transformation comme ci-dessous.
<xsl:variable name="lookup" select="('documentFile')/> .
En outre, peut transmettre des paramètres de chaîne simples comme ci-dessous, sans aucun problème comme ci-dessous:
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));
Mais, je veux passer un document XML en tant que paramètre au fichier XSL. J'ai essayé le code ci-dessous comme suggéré sur l'une des pages SO, comme ci-dessous:
transformer.setParameter("mode", "CREATE");
Et j'ai défini la balise en XML pour recevoir la valeur ci-dessous:
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);
Mais ça ne marche pas pour moi. Quelqu'un peut-il m'aider avec le bon salaire pour transmettre plusieurs documents XML à n'importe quel fichier XSL via l'API javax.xml.transform?
Mise à jour
Toujours bloqué avec le problème, quelqu'un peut-il me laisser comment puis-je passer un objet XML dans une feuille de style XSLT 2.0 en tant que paramètre. J'ai essayé différentes approches mais pas encore de chance. J'ai besoin de connaître un moyen de sortir via l'API de transformation JAVA xsl.
5 Réponses :
Vous n'êtes pas sûr de votre problème, si vous donnez un cas d'utilisation et demandez comment le résoudre, il sera plus utile de vous demander comment corriger votre code car nous n'avons pas la visibilité de bout en bout de votre code et xml.
Ce qui suit pourrait être une solution possible:
1) Nous pouvons convertir xml en chaîne
public class Data { public static final Document transformXmlDocument(Document sourceDocument, InputStream xsltFile) { DOMSource xmlSource = new DOMSource(sourceDocument); StreamSource xsltSource = new StreamSource(xsltFile); Document transformedData = null; try { TransformerFactory factory = TransformerFactory.newInstance(); Transformer transformer = factory.newTransformer(xsltSource); ByteArrayOutputStream output = new ByteArrayOutputStream(); StreamResult result = new StreamResult(output); transformer.transform(xmlSource, result); DocumentBuilder resultBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); transformedData = resultBuilder.parse( new InputSource( new StringReader( new String(output.toByteArray()) ) ) ); } catch (Exception e) { Log.e("XSLT Transformation", e.getMessage()); } return transformedData; } }
2) Modifiez le code ci-dessous selon vos exigences passer en tant que liste d'objet d'appel dans la boucle for.
try { StringReader _reader = new StringReader("<xml>vkhan</xml>"); StringWriter _writer = new StringWriter(); TransformerFactory tFactory = TransformerFactory.newInstance(); Transformer transformer = tFactory.newTransformer( new javax.xml.transform.stream.StreamSource("styler.xsl"));//ur xsl transformer.transform( new javax.xml.transform.stream.StreamSource(_reader), new javax.xml.transform.stream.StreamResult(_writer)); String result = writer.toString(); } catch (Exception e) { e.printStackTrace(); }
Si cela ne vous aide pas, veuillez mettre à jour votre code java complet et exemple xml et exigences.
Salut vaquar, merci pour votre réponse. Je ne vous demande pas de corriger mon code. Je suis déjà en mesure de fournir un XML comme entrée comme vous l'avez montré ci-dessus. Je souhaite transmettre des fichiers XML supplémentaires à mon fichier XSL pour effectuer des transformations. C'est pourquoi je veux passer un fichier XML comme paramètre supplémentaire, c'est mon cas d'utilisation pour être précis. J'ai essayé différentes approches, mais aucune d'entre elles ne fonctionne bien pour moi. Faites-moi savoir si vous pouvez aider, merci !!
plz update sample json dans votre question car vous avez besoin de json d'entrée pour résoudre le problème
(Réponse développée pour gérer le passage d'un document DOM W3C analysé via un URIResolver)
Cela peut être fait en XSLT / XPath pur en utilisant la version du processeur Xalan XSLT fourni avec le JRE.
À titre d'exemple, disons si le nom de l'un des documents d'entrée est passé en paramètre au Transformer
:
<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>
Essayez de remplacer votre instruction
par
et passez votre document XML en paramètre avec transformer.setParameter ("lookup", "myfile.xml");
ce qui signifie: charger le document référencé par le paramètre lookup dans la variable documentFile
.
Voir aussi Extraire des données d'un fichier XML externe à l'aide de XSL a >
Avez-vous déjà essayé ceci?
org.w3c.dom.Document doc = ... // Your xml document transformer.setParameter("demo", doc.getDocumentElement());
Je pense que votre problème concerne le XSLT. Remplacez
<?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>
par
@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); } }
cela obligera le transformateur à rendre le DOM
de votre document accessible dans le variable lookup
. La recherche
clé provient de docs.put ("lookup", documentFile);
Exemple de travail complet:
Soyez là trois fichiers XML: repo.xml
, books.xml
et articles.xml
. Le repo.xml
contient des informations sur l'état des livres et des articles. Les fichiers articles.xml
et books.xml
contiennent des informations sur le titre de chaque élément. L'objectif est d'imprimer les informations d'état de tous les livres et articles avec les informations de titre. Les entrées de tous les fichiers sont connectées via les touches id
.
Trouvez l'exemple complet sur github ou copiez / collez les listes ci-dessous.
repo.xml
<?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>
books.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>
articles.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>
join.xsl
<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>
Utilisez ce code Java ...
<xsl:variable name="lookup" select="document('lookup')/>
... pour produire cette sortie
<xsl:variable name="lookup" select="('documentFile')/> .
p>
Manipuler XSLT qui est du XML avec des espaces de noms avec un DocumentBuilder par défaut, pas compatible avec les espaces de noms et DOM Niveau 1, pas avec les espaces de noms createElement semble poser problème. Je suggère fortement de rendre compte de l'espace de noms DocumentBuilder et d'utiliser createElementNS
avec l'espace de noms XSLT.
Quel processeur XSLT utilisez-vous si vous posez des questions sur
java.xml.tansform
mais marquez la question comme xslt -2,0 ? Comme vous savez que XSLT depuis la version 1.0 dispose de la puissante fonctiondocument
qui permet de charger / accéder à des documents XML supplémentaires directement à partir de XSLT, même multiples en une seule étape?Salut Martin, je n'utilise aucun processeur en particulier, donc je suppose que le processeur XSLT par défaut est utilisé. Je sais que XSLT a une fonction de document puissante, mais je veux transmettre ce document via la fonction transformer.setParameter (), de la même manière que je passe les paramètres de chaîne ou d'entier, donc j'ai besoin de savoir comment nous faisons cela?
Toute aide serait appréciée !! :)
Eh bien, le processeur XSLT par défaut dans Oracle Java JRE est généralement une version internalisée de Xalan et Xalan n'est certainement pas un processeur XSLT 2, vous ne savez donc pas pourquoi vous avez marqué votre question pour cette version. Je suppose qu'un seul paramètre peut probablement être transmis en tant que document DOM du W3C ou peut-être Node en général.
Merci Martin !! Peut-être que je n'étais pas au courant de cela. Mais si je le définis comme un document DOM du W3C, je me demande quelle devrait être l'expression correcte du côté XSLT pour la recevoir.
J'espère que c'est aussi simple que de faire
représente un nœud de document XSLT / XPath, par exemple vous pouvez utiliser
ou des expressions de chemin comme
.
transformer.setParameter ("doc1", yourDocumentNode)
côté Java puis avec XSLT le paramètre globalQuel est le lien entre votre question et stackoverflow.com/questions/13381698 ?
J'ai essayé cela, @jschnasse, mais cela n'a pas fonctionné pour moi. Est-ce que ça marche pour vous ?
Ai-je bien compris, que vous avez besoin de données provenant de plusieurs sources XML pour créer votre transformation finale? Est-ce votre cas d'utilisation?
Oui, vous avez raison à 100% !! Le lien que vous avez donné fonctionne pour vous ??? Parce que je ne peux pas le faire fonctionner, faites-moi savoir si vous avez modifié quelque chose.
Je n'ai pas encore essayé. J'essaie toujours de comprendre ce que vous voulez accomplir. C'est donc fondamentalement quelque chose comme discuté ici: stackoverflow.com/questions/16323750 ?! Vous pouvez essayer de construire votre XSL à la volée en utilisant les mécanismes décrits. par exemple. (1) lu dans un XSL de base préparé comme XML-DOM (2) ajoute de nouveaux éléments à la source dans vos fichiers. (2) Passez le XSL modifié à votre transformateur.
Peut-être simplement changer
? Voyez ma réponse.