Ajout de noeud dans saxon via XPATH + API Saxon HE 9.3 ne fonctionne pas

Le
ALaRechercheDuTempsPerdu
Bonjour,

J'execute une requête XPATH pour selectionner un noeud depuis un
document source
Modifier certains attributs via mon appli java
Injecter le noeud résultant dans un doc XML cible.

Je précise que je n'utilise pas XSLT sciemment :)

Mon problème est le suivant : au moment de sérialiser mon nouveau
document, le document enregsitré est identique à l'ancien, comme si
l'appel à Append n'avait rien fait.

Voici le code :

XdmValue source = parseXmlDocument(xmlSource);
logger.info("XML parsed.");

try
{
// Fetch node to append
String xpathQuery = "/client/voiture/mode[@name='Chevrolet']";
XPathExecutable _XPathExecutable = getXpathEvaluator(xpathQuery);
XPathSelector xps = _XPathExecutable.load();
xps.setContextItem((XdmItem) source);
XdmValue child = xps.evaluate();
logger.info("Child node fetched.");

// Append node to source.
XdmValue newDocumentRoot = source.append(child);
logger.info("Child node appended.");

// Save to disk.
Serializer serializer = getSaxonSerializer(xmlSource);
XdmNode newDocumentRootNode = (XdmNode) newDocumentRoot.itemAt(0);
serializer.serializeNode(newDocumentRootNode);
logger.info("file saved.");

Est-ce quelqu'un pourrait m'expliquer ce que je fais mal ?

Merci pour vos lumières !
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Alain Ketterlin
Le #23463411
ALaRechercheDuTempsPerdu
J'execute une requête XPATH pour selectionner un noeud depuis un
document source
Modifier certains attributs via mon appli java
Injecter le noeud résultant dans un doc XML cible.

Je précise que je n'utilise pas XSLT sciemment :)



En fait tu n'utilises pas XSLT ici, seulement XPath et ce n'est pas le
problème.

XdmValue source = parseXmlDocument(xmlSource);



source est un noeud document (son premier fils est l'élément raci ne)
= (DOC (client ...))

// Append node to source.
XdmValue newDocumentRoot = source.append(child);



un nouveau noeud document avec deux éléments racines successifs
= (DOC (client ...) (mode ...))

(au passage, ça ne devrait pas être autorisé, avec un DOM co nforme tu
devrais prendre une exception)

XdmNode newDocumentRootNode = (XdmNode) newDocumentRoot.itemAt(0);



récupère l'ancienne racine (qui est toujours là).
= (client ...)

-- Alain.
Yliur
Le #23463491
Bonjour

Mon problème est le suivant : au moment de sérialiser mon nouveau
document, le document enregsitré est identique à l'ancien, comme si
l'appel à Append n'avait rien fait.



Je ne connais pas la bibliothèque mais quelques remarques, sait-on
jamais...

XdmValue source = parseXmlDocument(xmlSource);
logger.info("XML parsed.");

try
{
// Fetch node to append
String xpathQuery = "/client/voiture/mode[@name='Chevrolet']";
XPathExecutable _XPathExecutable = getXpathEvaluator(xpathQuery);
XPathSelector xps = _XPathExecutable.load(); xps.setContextItem((XdmItem) source);
XdmValue child = xps.evaluate();
logger.info("Child node fetched.");



Bon, là pour la forme on pourrait vérifier que le bon noeud a été
récupéré.

// Append node to source.
XdmValue newDocumentRoot = source.append(child);
logger.info("Child node appended.");



Est-il possible de vérifier que le noeud fils a été correctement
inséré ?

// Save to disk.
Serializer serializer = getSaxonSerializer(xmlSource);



Je suppose que xmlSource est simplement le chemin du fichier source ?

XdmNode newDocumentRootNode = (XdmNode) newDocumentRoot.itemAt(0);



Pourquoi récupérer un élément ? Est-ce qu'il ne faut pas sauver la
racine ? Quel est cet élément à l'emplacement 0 ? Est-ce la bonne
racine ? Est-ce que l'élément ajouté ne se trouve pas à côté (à
l'emplacement 1) ?

serializer.serializeNode(newDocumentRootNode);
logger.info("file saved.");



Voilà, en espérant qu'un peu de trace permette de résoudre le
problème :) .
Yliur
Le #23463481
Ah... grillé par un voisin :)
ALaRechercheDuTempsPerdu
Le #23464141
Bonjour,

J'ai continué à chercher :)
Pour la remarque sur le fait que je me retrouve avec 2 éléments
racine, ce qui est invalide, c'est tout à fait exact !

Du coup, j'ai changé mon fusil d'épaule :

1 Chargement d'un DOM Source classique
2 Wrap dans un Saxon XdmItem du DomSourcepour faire la requete XPath
3 Injection du noeud récupéré dans mon DomSource d'origine après
modification du noeud.
4 Sauvegarde du nouveau domsource (celui de départ + le noeuf
modifié).

Je bloque sur le 3 :
Comment transformer mon XdmValue en Node pour pouvoir faire le
appendChild ?

Extarct de code :
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
javax.xml.parsers.DocumentBuilder builder =
factory.newDocumentBuilder();
Document domRoot = builder.parse(xmlSource);

String msg = String.format("%s has been read.",
xmlSource.getName());
logger.info(msg);


// Injection dom source into saxon framework
DocumentBuilder saxonBuilder = processor.newDocumentBuilder();
saxonBuilder.setTreeModel(TreeModel.LINKED_TREE);
Source s = new DOMSource(domRoot);
XdmNode saxonDocument = saxonBuilder.build(s);

String xpathQuery = "/chevrolet[1]";
XPathExecutable _XPathExecutable = getXpathEvaluator(xpathQuery);
XPathSelector xps = _XPathExecutable.load();
xps.setContextItem(saxonDocument);
XdmNode child = (XdmNode)xps.evaluateSingle();

// Append node to source.
//String msg = String.format("Collection size before : %d",
source.size());
//logger.info(msg);

// C'est la suite qui bloque, au moment d'injecter le résultat de la
requête, j'arrive pas à trouver le chemin pour caster :(
NodeInfo ni = child.getUnderlyingNode();

domRoot.adoptNode(ni);

Merci pour votre aide en tout cas !
Alain Ketterlin
Le #23464271
ALaRechercheDuTempsPerdu
1 Chargement d'un DOM Source classique
2 Wrap dans un Saxon XdmItem du DomSourcepour faire la requete XPath
3 Injection du noeud récupéré dans mon DomSource d'origine après
modification du noeud.



Tu n'as toujours pas dit à quel endroit tu voulais insérer le noe ud.
D'autre part, le même noeud ne peut pas apparaître deux fois dans un
arbre (par définition) : il faudra donc le cloner, puis insérer s on
clone.

4 Sauvegarde du nouveau domsource (celui de départ + le noeuf
modifié).

Je bloque sur le 3 :
Comment transformer mon XdmValue en Node pour pouvoir faire le
appendChild ?



Il n'y a aucune raison que ce soit possible. Après :

XdmNode saxonDocument = saxonBuilder.build(s);



il n'est pas sûr que les nodes saxon fassent encore référenc e aux nodes
DOM. Il vaudrait mieux choisir l'un ou l'autre.

-- Alain.
ALaRechercheDuTempsPerdu
Le #23464401
On 15 juin, 15:45, Alain Ketterlin wrote:
ALaRechercheDuTempsPerdu > 1 Chargement d'un DOM Source classique
> 2 Wrap dans un Saxon XdmItem du DomSourcepour faire la requete XPath
> 3 Injection du noeud récupéré dans mon DomSource d'origine aprè s
> modification du noeud.

Tu n'as toujours pas dit à quel endroit tu voulais insérer le noeud.
D'autre part, le même noeud ne peut pas apparaître deux fois dans un
arbre (par définition) : il faudra donc le cloner, puis insérer son
clone.

> 4 Sauvegarde du nouveau domsource (celui de départ + le noeuf
> modifié).

> Je bloque sur le 3 :
> Comment transformer mon XdmValue en Node pour pouvoir faire le
> appendChild ?

Il n'y a aucune raison que ce soit possible. Après :

>XdmNodesaxonDocument = saxonBuilder.build(s);

il n'est pas sûr que les nodes saxon fassent encore référence aux n odes
DOM. Il vaudrait mieux choisir l'un ou l'autre.

-- Alain.



Ah exact, je vais l'inserer dans un des enfants du dom, pour cela, je
comptais faire un getChild sur le modèle DOM.
Pour le point du clone, en réalité, le noeud copié provient d'un autr e
document source sur lequel j'ai fait une requete XPath.

Pour utiliser le saxon builder c'est bonne idée, j'ai juste un pb pour
faire l'append sur le child correct.
Peut-être que je devrai faire une requête xpath pour déterminer le
point d'insertion et faire l'append dessus: j'obtiens alors e2.

Mais j'aurai tjs le même pb: comment rattacher le nouvel element e2
dans le document saxon :(
ALaRechercheDuTempsPerdu
Le #23467071
Bon, après une tentative infructueuse d'utiliser ceci :
Processor proc = new Processor(false);

Serializer serializer = getSaxonSerializer(new File("xmlConfDir",
"output.xml"));
proc.writeXdmValue(child, dest);

je vais sérialiser mon child en mémoire, construire un nouveau doc xml
avec ce child puis l'importer dans mon doc destination.
quelle est la classe de output stream pour travailler en mémoire
déjà .... hmm javadoc to my rescue :)
Publicité
Poster une réponse
Anonyme