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 :

Parcour d’un fichier XML


Sujet :

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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    162
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2014
    Messages : 162
    Par défaut Parcour d’un fichier XML
    Bonjour tout le monde,

    Un petit problème m’empêche de terminer mon projet.

    Je dois parcourir un fichier XML, j’ai découvert JDOM (j’utilise la version 2.0.6) il y a quelques heures et j’aimerais savoir comment le faire fonctionner. J’ai vu l’existence d’un tutoriel. Utile ce tutoriel :) mais l’architecture de mon fichier XML, n’est pas la même, j’ai donc du mal à reproduire la méthode.

    Code XML : 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
    <?xml version="1.0" encoding="UTF-8"?>
    <sites>
    	<site id="bl" name="bl.com">
    		<countries>
    			<country id="fr">
    				<servers>
    					<server name="1.bl.p1.ci" />
    					<server name="2.bl.p1.ci" />
    					<server name="3.bl.p1.ci" />
    				</servers>
    			</country>
    		</countries>
    	</site>
     
    	<site id="ca" name="ca">
    		<countries>
    			<country id="fr">
    				<servers>
    					<server name="7.bl.p1.ci" />
    					<server name="8.bl.p1.ci" />
    					<server name="9.bl.p1.ci" />
    				</servers>
    			</country>
    			<country id="de">
    				<servers>
    					<server name="4.bl.p1.ci" />
    					<server name="5.bl.p1.ci" />
    					<server name="6.bl.p1.ci" />
    				</servers>
    			</country>
    		</countries>
    	</site>
    </sites>

    et mon code JAVA

    Code JAVA : 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
    public void TestXmlReader(){
    		SAXBuilder builder = new SAXBuilder();
    		File xmlFile = new File("/home/user/workspace/search-lms/lms-superpom/lms-admin/src/main/resources/lms-admin.xml");
     
    		try {
     
    			Document document = (Document) builder.build(xmlFile);
    			Element rootNode = document.getRootElement();
    			List<Element> list = rootNode.getChildren("site");
     
    			Iterator<Element> i = list.iterator();
    			while(i.hasNext()){
    				Element current = (Element)i.next();
     
    				System.out.println(current.getAttributeValue("id"));
                                    System.out.println(current.getChild("countries").getAttributeValue("id"));
                                    System.out.println(current.getChild("countries").getChild("country").getAttributeValue("id"));
                                    System.out.println(current.getChild("countries").getChild("country").getChild("servers").getChild("server").getAttributeValue("name"));
    			}
     
    		  } catch (IOException io) {
    			System.out.println(io.getMessage());
    		  } catch (JDOMException jdomex) {
    			System.out.println(jdomex.getMessage());
     
    		  }

    J’ai plus ou moins réussi à afficher un résultat, en faisant ce truc archi-dégeu, mais j’obtiens : « bl null fr 1.bl.p1.ci ca null fr 7.bl.p1.ci ». Je ne vois pas le « de », ni les autres noms des serveurs :(

    Dois-je déclarer un autre Iterator sur une liste qui prendrait comme racine « country » ?

    Dans ce genre là (ne fonctionne pas):

    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    List<Element> list2 = rootNode.getChildren("country");
    Iterator<Element> j = list2.iterator();
     
    while(i.hasNext()){
        while(j.hasNext()){
    	Element current2 = (Element)j.next();
     
    	System.out.println(current2.getAttributeValue("id"));
    	System.out.println(current2.getChild("servers").getChild("server").getAttributeValue("name"));
        }
    			}

    Autrement, je suis en train de lire la documentation suivante (en anglais), on va voir si elle peut m’être utile.

    Avez-vous une idée de comment faire ça mieux (et que ça fonctionne ^^') ?

  2. #2
    Membre Expert Avatar de jeffray03
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2008
    Messages
    1 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 501
    Par défaut
    Salut,
    voici un exemple vite fait,
    si cela peux t´aider.
    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    public class RecursiveDOM {
    	private static String nomFichier = "test.xml";
     
    	public static void main(final String[] args)
    			throws ParserConfigurationException, SAXException, IOException {
    		DocumentBuilder builder = DocumentBuilderFactory.newInstance()
    				.newDocumentBuilder();
    		Document doc = builder.parse(nomFichier);
    		doc.normalize();
    		parseXML(doc.getFirstChild(), null, 0);
    		// nodeList = racine.getElementsByTagName(tagName);
    	}
     
    	public static void parseXML(Node node, Node parent, int anzLeerZeichen) {
     
    		if (node.hasChildNodes()) {
    			printSpace(anzLeerZeichen);
    			System.out.println(node.getNodeName());
    			NodeList childrens = node.getChildNodes();
    			NamedNodeMap nodeMap = node.getAttributes();
     
    			for (int i = 0; i < nodeMap.getLength(); i++) {
     
    				Node nodetemp = nodeMap.item(i);
    				printSpace(anzLeerZeichen + 3);
    				System.out.println("attr name : " + nodetemp.getNodeName());
    				printSpace(anzLeerZeichen + 3);
    				System.out.println("attr value : "
    						+ nodetemp.getNodeValue());
     
    			}
    			for (int i = 0; i < childrens.getLength(); i++) {
    				parseXML(childrens.item(i), node , anzLeerZeichen++);
    			}// for
    		}// fi:root_childrens
    		else {
    			String nodeValue = "";
    			if (node.getNodeValue() != null) {
    				nodeValue = node.getNodeValue().trim();
    				if (nodeValue.length() > 0) {
    					System.out.println(parent.getNodeName() + "::" + nodeValue);
    				}
    			} else if (node.getNodeName() != null) {
    				nodeValue = node.getNodeName().trim();
    				// get attributes names and values
    				if (nodeValue.length() > 0) {
    					printSpace(anzLeerZeichen);
    					System.out.println(parent.getNodeName() + "::" + nodeValue);
    				}
    				NamedNodeMap nodeMap = node.getAttributes();
     
    				for (int i = 0; i < nodeMap.getLength(); i++) {
     
    					Node nodetemp = nodeMap.item(i);
    					printSpace(anzLeerZeichen + 3);
    					System.out.println("attr name : " + nodetemp.getNodeName());
    					printSpace(anzLeerZeichen + 3);
    					System.out.println("attr value : "
    							+ nodetemp.getNodeValue());
     
    				}
    				anzLeerZeichen = 1;
    			}
    		}
    	}
     
    	private static void printSpace(int anz) {
    		if(anz>0)
    		System.out.print(String.format("%" + anz + "s", "").replace(' ', ' '));
    	}
    }
    Eric

  3. #3
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    162
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2014
    Messages : 162
    Par défaut
    Merci pour ta réponse :)

    Cependant, il est vrai que le code est assez long. Peut-être est-ce dû au fait que tu n’utilises pas JDOM (je ne sais pas).
    Peut-être que c’est mieux sans JDOM.


    J’ai continué à chercher, j’ai trouvé quelque chose que ressemblant à ça :
    Code JAVA : 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
    public void TestXmlReader() throws IOException, JDOMException {
     
    		SAXBuilder builder = new SAXBuilder();
    		Document document = builder.build("/home/user/workspace/search-lms/lms-superpom/lms-admin/src/main/resources/lms-admin.xml");
    		Element rootNode = document.getRootElement();
     
    		System.out.println(rootNode);
     
     
    		if("sites".equals(rootNode.getName())){
    			List<String> items = new ArrayList<String>();
    			for(Element site : rootNode.getChildren("site")){
    				for(Element countries : site.getChildren("countries")){
    					for(Element country : countries.getChildren("country")){
    						items.add(country.getAttributeValue("id"));
    						for(Element servers : country.getChildren("servers")){
    							for(Element server : servers.getChildren("server")){
    								items.add(server.getAttributeValue("name"));
     
    							}
    						}
    					}
    				}
    			}
    			System.out.println(items);
    		}
     
    	}

    J’obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [Element: <sites/>] [fr, threes1.be.p1.ciao, threes2.be.p1.ciao, threes3.be.p1.ciao, fr, threes7.be.p1.ciao, threes8.be.p1.ciao, threes9.be.p1.ciao, de, threes4.be.p1.ciao, threes5.be.p1.ciao, threes6.be.p1.ciao]
    Ce est plutôt le résultat attendu. Mais j’aimerais bien le récupérer sous une autre forme, plus facile à séparer…
    Il faudrait que je trouve un système pour dire : quelque soit le nombre de serveurs, de pays ou de site que je rajoute, je veux que cet objet (un tableau, une variable ou autre chose) contienne le nom d’un site puis un pays de ce site avec les serveurs qui vont ensemble et recommencer tant qu’il reste des pays. Je ne sais pas s’il faudrait un objet pour chaque site ou non.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    Déjà, il faut analyser le modèle :

    • On a des sites, caractérisés par un id et un nom.
    • Qui ont plusieurs pays, qui ne sont caractérisés que par un identifiant ISO3166 à priori. Les pays sont en commun aux différents serveurs.
    • Pour chaque pays on a une liste de serveurs (un nom). A priori un serveur ne peut se trouver que dans un site.


    Les informations des pays étant limitées à des String, on peut utiliser des String, mais caractériser chaque type d'information peut permettre de mieux gérer par la suite, et d'ajouter le cas échéant des attributs ou des comportements (méthodes).
    Pour un serveur, cela peut être intéressant d'utiliser une classe, avec un attribut nom et un attribut pays (String ou une classe personnelle Country selon).
    Pour un site, il vaut mieux utiliser une classe, avec un attribut id (String), un attribut nom (String).
    Ensuite, il faut également considérer comment tu veux pouvoir récupérer une information par rapport à une autre... est-ce que c'est la classe Site qui a un attribut liste de serveurs (List<Server>, ou List<String>), ou est-ce qu'une instance de Server a un attribut de type Site, ou bien est-ce les deux ?

    Pour le stockage, dans le principe d'un parcourt arborescent, au fur et à mesure du parcourt (comme tu l'as fait dans ton code JDOM), on peut utiliser :

    • une liste de sites (List<Site>) permet de stocker les sites, pour chaque élément Site
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      currentSite = new Site( attributId, attributName);
      siteList.add(currentSite);
      siteList peut être le résultat final : la liste de tous les sites lus.
      currentSite est le site en cours de décodage, auquel on peut ajouter les serveurs au fur et à mesure qu'on lit les éléments server : currentSite.addServer(new Server(...))on peut également faire Server currentServer = new Server(..., currentSite); si on veut que le serveur connaisse son site (avec un attribut site)
    • une map peut être utilisée lorsque tu veux pouvoir retrouver un élément qui a un id,

      Par exemple, au moment de la lecture de l'élément country, avec une classe Country :

      en Java <=7
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
       
      String countryId = countryElement.getAttributeValue("id"));
       
      final Country currentCountry;
      if ( !countryMap.contains( countryId ) ) {
          currentCountry = countryMap.get(countryId);
      }
      else {
          currentCountry = new Country(countryId);
          countryMap.put(countryId,currentCountry);
      }
      en Java 8 :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      final Country currentCountry = map.computeIfAbsent(countryId, id-> new Country(id));
      Ce qui permet à chaque lecture d'élément serveur :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      currentServer = new Server(serverId, currentCountry, currentSite);
      currentSite.addServer(currentServer );
    • Dans ce type de lecture arboresence, on peut utiliser une pile aussi (ArrayDeque par exemple) : à chaque fois qu'on entre dans un niveau, on créé l'instance correspondante, push( instance ) permettant d'empiler, pop() permettant de dépiler (le dernier empilé), et peek() permettant de lire le dernier empilé.
      Ainsi, au lieu d'avoir des variables currentCountry de type Country, on peut utiliser une pile countryStack, de type Deque<Country>, faire countryStack.push( map.computeIfAbsent(countryId, id-> new Country(id)) à chaque lecture d'élément country, new Server(serverId, countryStack.peek(), currentSite); pour chaque server, et quand on termine la boucle sur les serveurs d'un pays, faire currentCountry.pop().
      Dans ton cas, ce n'est pas vraiment utile je pense (plus lourd que d'avoir une simple variable, mais c'est plutôt utile lorsqu'on a plusieurs niveaux récursivement de même type.


    Tu obtiens ainsi, au choix, une liste de Site, de Server, voire de pays si tu veux, ou une map de sites (avec pour clef l'id de site), de serveurs..., ... selon tes besoins de manipulation ultérieurs.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre très actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2014
    Messages
    162
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Décembre 2014
    Messages : 162
    Par défaut Parcours d’un fichier XML
    Merci beaucoup pour cette réponse

    Effectivement, ça m’a l’air d’être une très bonne idée de faire une classe et d’y inclure les éléments après. Je vais étudier cette solution de plus près.

    J’ai écris ça, qui me donne un résultat, pour l’instant, satisfaisant, mais qui, me montrera vite ses limites :

    Code JAVA : 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
    @Test
    	public void TestXml() throws JDOMException, IOException {
    		String fileName = "/home/user/workspace/search-lms/lms-superpom/lms-admin/src/main/resources/lms-admin.xml";
    		SAXBuilder builder = new SAXBuilder();
    		Document document;
    		document = builder.build(fileName);
    		Element rootNode = document.getRootElement();
     
    		ArrayList<Site> siteList = new ArrayList<Site>();
    		Site currentSite;
     
    		if("sites".equals(rootNode.getName())){
     
     
    			for(Element site : rootNode.getChildren("site")){
    				currentSite = new Site();
    				currentSite.add(site.getAttributeValue("id"));
    				for(Element countries : site.getChildren("countries")){
    					for(Element country : countries.getChildren("country")){
    						currentSite.add(country.getAttributeValue("id"));
    						for(Element servers : country.getChildren("servers")){
    							for(Element server : servers.getChildren("server")){								
    								currentSite.add(server.getAttributeValue("name"));
    							}
    						}
    					}
    				}
    				siteList.add(currentSite);
     
    			}
    			System.out.println(siteList);
    		}
    	}

    Avec la classe Site :

    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    import java.util.ArrayList;
     
    public class Site extends ArrayList<String>{
     
    	public Site() {
     
    	}
     
    }

    Résultat : [[BL, FR, 1.bl.p1.ci, 2.bl.p1.ci, 3.bl.p1.ci], [CA, FR, 7.bl.p1.ci, 8.bl.p1.ci, 9.bl.p1.ci, DE, 4.bl.p1.ci, 5.bl.p1.ci, 6.bl.p1.ci], [ZE, FR, null]]

Discussions similaires

  1. [XL-2003] Importer en Excel des données d’un fichier XML
    Par luca.donati dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 11/11/2010, 02h16
  2. Lecture dun fichier xml avec python
    Par merlinerick dans le forum Interfaçage autre langage
    Réponses: 6
    Dernier message: 29/07/2009, 13h49
  3. [JDOM] Parcours de fichier xml
    Par sabrinabest dans le forum Format d'échange (XML, JSON...)
    Réponses: 6
    Dernier message: 20/09/2007, 12h00
  4. [DOM] problème lors du parcours du fichier xml
    Par krfa1 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 11/05/2007, 07h24
  5. iReport à partir d’un fichier XML
    Par jproto dans le forum iReport
    Réponses: 6
    Dernier message: 13/02/2007, 09h11

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