IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Format d'échange (XML, JSON...) Java Discussion :

Inversions d'attributs avec DOM [DOM]


Sujet :

Format d'échange (XML, JSON...) Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 187
    Points : 110
    Points
    110
    Par défaut Inversions d'attributs avec DOM
    Bonjour,

    Je suis sur un projet dans lequel je dois à un moment ouvrir un fichier XML pour y rajouter des balises. Vu que ce n'est pas bien compliqué en théorie, je fais ça avec dom directement.

    L'ajout de balise fonctionne bien, cependant j'avais deux problèmes initialement (je ne faisait pas encore le lien avec la DTD) :

    Le premier était la disparition de la balise xmlns dans l'élément racine de mon XML ( ça, à priori, c'est pas trop grave) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://..." id="COS-PLANS-LNKS-PROD-TDPV41-01" CosType="product">
    ....
    </TDPCos>
    deviens alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos id="COS-PLANS-LNKS-PROD-TDPV41-01" CosType="product">
    ....
    </TDPCos>
    jusque là, rien de bien grave donc, mais vient alors le second souci, les attributs de mes balises n'ont pas leur ordre initial qui est conservé, ce qui fait qu'au final :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://..." id="COS-PLANS-LNKS-PROD-TDPV41-01" CosType="product">
    ....
    </TDPCos>
    deviens alors :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos CosType="product" id="COS-PLANS-LNKS-PROD-TDPV41-01">
    ....
    </TDPCos>
    Ca ne m'a pas vraiment choqué au début mais un autre programme ( que je ne doit pas modifier) recherche l'ID de l'objet TDPCos comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    theCurrentObjectID = theParser.getAttributeValue(0);
    Ce qui fait que bien sûr, du coup, ça marche plus vu que l'attribut récupéré est maintenant "CosType" et non plus "id"

    mon code initial était fait comme ça :

    création du document :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	public Document getDomDocument() throws ParserConfigurationException, SAXException, IOException {
    		if (domDocument == null) {
    			DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
    			DocumentBuilder constructeur = fabrique.newDocumentBuilder();
    			domDocument = constructeur.parse(fusFile);
    		}
    		return domDocument;
    	}
    modification du document

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    //add the tags
    		while (index < fusObjects.getLength()) {
    			Node node = fusObjects.item(index);
    			NamedNodeMap attributes = node.getAttributes();
    			if (attributes != null && attributes.getNamedItem("id") != null) {
    				Node idAttribute = attributes.getNamedItem("id");
    				String idValue = idAttribute.getNodeValue();
    				copiedObjects.add(idValue);
    				//check that the tag is one that must be modified
    				if (tagsList.containsKey(idValue)) {
    					ArrayList<Element> tagsForThisObjects = tagsList.get(idValue);
    					for (Element tag : tagsForThisObjects) {
    						//check that the link don't exist yet
    						if (!nodeHaveTag((Element) node, tag, idValue)) {
    							node.appendChild(tag);
    						}
    					}
    				}
    			}
    			index++;
    		}
    Et enfin sauvegarde du document dans le fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	public void saveToFile() throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException, IOException {
    		DOMSource domSource = new DOMSource(domDocument);
    		StringWriter writer = new StringWriter();
    		StreamResult result = new StreamResult(writer);
    		TransformerFactory tf = TransformerFactory.newInstance();
    		Transformer transformer = tf.newTransformer();
    		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    		transformer.transform(domSource, result);
    		FileWriter fileWriter = new FileWriter(fusFile);
    		fileWriter.write(writer.toString());
    		fileWriter.close();
    	}
    J'ai ensuite essayé de rajouter un lien vers la XSD, mon code de création du document est alors devenu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    	public Document getDomDocument() throws ParserConfigurationException, SAXException, IOException {
    		if (domDocument == null) {
    			DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
     
    			fabrique.setIgnoringComments(true);
    			fabrique.setNamespaceAware(true);
    			fabrique.setValidating(true);
    			fabrique.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
    			fabrique.setAttribute(JAXP_SCHEMA_SOURCE, getXSDFile());
    			DocumentBuilder constructeur = fabrique.newDocumentBuilder();
    			domDocument = constructeur.parse(fusFile);
    		}
    		return domDocument;
    	}
    Résultat des courses, mes attributs sont toujours dans le désordre ( je pensais que le fait de lier à la XSD forcerai peut être à conserver l'ordre des attributs, mais visiblement ça ne fait que de la validation), j'ai quelques erreurs dans mon log du au fait que mon XML d'entrée ne respecte déjà pas exactement la XSD, et dans chaque balise que je rajoute j'ai maintenant un attribut vide qui a apparu

    Bref je comprend plus grand chose, je sais plus trop ce je dois rajouter et à quel moment pour que mon XML de sortie soit strictement égal à mon XML d'entrée, avec mes balises que je rajoute en plus....

    Toute aide est la bienvenue, il faudrai pour bien aller j'ai terminé ça avant ce soir 17h et je sens que tout seul je vais pouvoir tatonner un moment !!

    merci

  2. #2
    Expert éminent

    Avatar de mlny84
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    4 023
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 4 023
    Points : 8 107
    Points
    8 107
    Par défaut
    Bonjour,

    Je t'avoue que je ne maitrise pas totalement la chose, mais voici quelques éléments de réponses qui pourront peut être t'aider.

    Tes attributs ne sont pas dans l'ordre car tu utilises la méthode getAttributes de la classe Node, elle te renvoie une NamedNodeMap dont les éléments ne sont pas triés :

    Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
    Il faudrait donc trouver une autre solution, laquelle ? Je ne sais pas.

    Concernant ton problème de namespace, si ce n'est pas grave pour toi de le supprimer, tu peux essayer de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fabrique.setNamespaceAware(false);
    J'espère t'avoir au moins aidé un peu.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 187
    Points : 110
    Points
    110
    Par défaut
    Merci beaucoup j'ai pas la solution mais j'ai déjà le problème c'est déjà pas mal !

    Je dois avouer que je commençait à être un peu à sec et ça m'arrage d'avoir des nouvelles pistes de recherche !

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 187
    Points : 110
    Points
    110
    Par défaut
    Bon en fait le problème viens pas de là... pas complètement en tout cas...

    j'ai commenté tout le code de modification ( pour que mes balises ne se rajoutent plus), il reste donc plus que :

    la création du document :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    public Document getDomDocument() throws ParserConfigurationException, SAXException, IOException {
    		if (domDocument == null) {
    			DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
    			fabrique.setNamespaceAware(false);
    			fabrique.setValidating(true);
    			fabrique.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
    			fabrique.setAttribute(JAXP_SCHEMA_SOURCE, getXSDFile());
    			DocumentBuilder constructeur = fabrique.newDocumentBuilder();
    			domDocument = constructeur.parse(fusFile);
    		}
    		return domDocument;
    	}
    et la sauvegarde du document :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    	public void saveToFile() throws TransformerFactoryConfigurationError, TransformerConfigurationException, TransformerException, IOException {
    		DOMSource domSource = new DOMSource(domDocument);
    		StringWriter writer = new StringWriter();
    		StreamResult result = new StreamResult(writer);
    		TransformerFactory tf = TransformerFactory.newInstance();
    		Transformer transformer = tf.newTransformer();
    		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    		transformer.transform(domSource, result);
    		FileWriter fileWriter = new FileWriter(fusFile);
    		fileWriter.write(writer.toString());
    		fileWriter.close();
    	}
    et j'ai toujours comme résultat dans mon fichier fusFile :

    - avant le traitement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://dcn.fr/fus" id="COS_PARTDOCLINK_1" CosType="product">
    - après le traitement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos CosType="product" id="COS_PARTDOCLINK_1">
    Bon et bien sûr, il n'y a aucune autre modification dans le document, tout est commenté...

    Le problème vient surement du coup de mon chargement du fichier ou de l'écriture, mais je vois pas torp comment l'éviter...

    Quelqu'un aurait il d'autres suggestions??

    merci !

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 187
    Points : 110
    Points
    110
    Par défaut
    Bon je poste mon dernier test, peut être que ça inspirera quelqu'un !

    J'ai fait un programme minimal qui ouvre le xml original (1), l'enregistre dans un fichier (2), reouvre le fichier (2) et l'enregistre dans un fichier (3)...

    voilà mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    		File fichier = new File("inversionatributdom\\fichier.xml");
    		File fichierEnr1 = new File("inversionatributdom\\fichierEnr1.xml");
    		File fichierEnr2 = new File("inversionatributdom\\fichierEnr2.xml");
     
    		//ouvre le fichier original et enregistre dans un second fichier
    		DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance();
    		fabrique.setNamespaceAware(false);
    		fabrique.setValidating(true);
    		fabrique.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
    		fabrique.setAttribute(JAXP_SCHEMA_SOURCE, getXSDFile());
    		DocumentBuilder constructeur = fabrique.newDocumentBuilder();
    		Document domDocument = constructeur.parse(fichier);
    		DOMSource domSource = new DOMSource(domDocument);
    		StringWriter writer = new StringWriter();
    		StreamResult result = new StreamResult(writer);
    		TransformerFactory tf = TransformerFactory.newInstance();
    		Transformer transformer = tf.newTransformer();
    		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
    		transformer.transform(domSource, result);
    		FileWriter fileWriter = new FileWriter(fichierEnr1);
    		fileWriter.write(writer.toString());
    		fileWriter.close();
     
    		//ouvre le second fichier et enregistre dans le 3eme fichier
    		DocumentBuilderFactory fabrique2 = DocumentBuilderFactory.newInstance();
    		fabrique2.setNamespaceAware(false);
    		fabrique2.setValidating(true);
    		fabrique2.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
    		fabrique2.setAttribute(JAXP_SCHEMA_SOURCE, getXSDFile());
    		DocumentBuilder constructeur2 = fabrique2.newDocumentBuilder();
    		Document domDocument2 = constructeur2.parse(fichierEnr1);
    		DOMSource domSource2 = new DOMSource(domDocument2);
    		StringWriter writer2 = new StringWriter();
    		StreamResult result2 = new StreamResult(writer2);
    		TransformerFactory tf2 = TransformerFactory.newInstance();
    		Transformer transformer2 = tf2.newTransformer();
    		transformer2.setOutputProperty(OutputKeys.INDENT, "yes");
    		transformer2.transform(domSource2, result2);
    		FileWriter fileWriter2 = new FileWriter(fichierEnr2);
    		fileWriter2.write(writer2.toString());
    		fileWriter2.close();
    Dans ce cas, je suis sûr qu'aucune modification ne doit être fait dans aucun XML...

    dans le fichier original (1), on a

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://dcn.fr/fus" id="COS_PARTDOCLINK_1" CosType="product">
    dans le fichier (2), on a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://dcn.fr/fus" CosType="product" id="COS_PARTDOCLINK_1">
    et dans le fichier (3), on a

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <?xml version="1.0" encoding="UTF-8"?>
    <TDPCos xmlns="http://dcn.fr/fus" CosType="product" id="COS_PARTDOCLINK_1">
    l'ordre est conservé du fichier (2) au fichier (3), je pense du coup que dom doit trier les attributs selon un certain critère... Ce qu'il me faudrait, c'est juste pouvoir désactiver ce "tri"...

    Enfin ce n'est qu'une supposition peut être que je fais fausse route, en tout cas, toute aide sera la bienvenue !!

    merci

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 466
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 466
    Points : 1 610
    Points
    1 610
    Par défaut
    Ben disons que les spécifications d'xml disent clairement que l'ordre des attributs n'a aucune signification (cf section 3.1 http://www.w3.org/TR/REC-xml/ ).
    Donc se baser la dessus, c'est chercher les pb.

    La plupart des processeurs trie par ordre alpha les attributs, majuscules, puis minuscules. C'est ce qui se passe là.

    Si tu n'a vraiment pas moyen de changer l'autre programme, je te conseille de changer l'ordre en traitant le fichier en tant que fichier texte avec des expression régulière.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 187
    Points : 110
    Points
    110
    Par défaut
    Merci pour ta réponse.

    On pensait pas que ce serai une telle galère pour juste conserver l'ordre des attributs... Du coup plutôt que de passer par des expressions régulières, on va modifier le premier programme...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Lire un attribut avec DOM
    Par adilou1981 dans le forum Débuter avec Java
    Réponses: 5
    Dernier message: 02/01/2014, 15h03
  2. [DOM] Récupérer les attributs d'un fichier XML en XPATH AVEC DOM
    Par jean22 dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 26/06/2013, 16h02
  3. [DOM] Question concernant dom et les attributs avec java
    Par zemzoum89 dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 30/09/2010, 20h18
  4. [PERL] lecture attribut avec DOM
    Par guenaule dans le forum APIs
    Réponses: 2
    Dernier message: 18/03/2008, 18h43
  5. [DOM] récupérer un attribut d'un xml avec DOM
    Par fonkyom dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 11/03/2008, 15h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo