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 :

[Regexp] splitter attribut tag xml


Sujet :

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

  1. #1
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut [Regexp] splitter attribut tag xml
    Bonjour,

    Je viens vous demander conseil sur l'un de mes problèmes actuels : je voudrais splitter un tag xml pour faire ressortir ses attributs.

    Voici l'exemple sur lequel je butte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TOTO id="019053695" type="B" la=" " status="1" c="HG" date="20071120"
    Jusqu'à maintenant je splitter simplement par rapport au caractère 'space', ce qui me permettait effectivement de retrouver un tableau d'attribut (sans compter le premier indice du tableau qui est le nom du tag (TOTO))
    Seulement dans le cas ici présent, lorsqu'un des attributs à pour valeur space (ce qui est possible dans mon document en entrée), ce split ne fonctionne plus et je me retrouve avec un élément dans mon tableau qui a pour valeur 'la="' au lieu de 'la="valeur"'.

    J'aimerai donc savoir s'il est possible de mettre en place une regexp permettant de découper correctement ma chaine de caractère ?

    J'ai tenté ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // --- Create a pattern to match breaks
    Pattern p = Pattern.compile("^([a-zA-Z_0-9]{1,}[=]\022.*\022)");
    // Split input with the pattern
    String[] result = p.split(myTagRepresentation);
    mais sans résultat probant :s
    Je en sais pas trop comment m'y prendre, j'aurais voulu découper selon ce qui ne valide pas le modèle suivant : nomAttribut="valeur" puisque ça ne fonctionne pas avec les espaces.

    Merci pour votre aide.

  2. #2
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    Autre solution envisageable, celle de reprendre la valeur matchée si cette dernière est trouvée dans la chaine de caractère en entrée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // --- Create a pattern to match breaks
    Pattern p = Pattern.compile("[a-zA-Z_0-9]{1,}[=\022].*[\022]");
    Matcher m = p.matcher(myTagRepresentation);
    while ( m.find() ){
    	m.??? // --- Comment faire pour récupérer le bout de chaine qui matche l'expression ?
    }
    Mais je ne trouve aucune méthode de la classe Matcher qui puisse retourner la valeur trouvée, quelqun a une idée ?

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    Dans les regexp le ^ désigne le début de la ligne... comme ton expression est incorrect. De plus le \022 représente un caractère invalide chez moi...


    A mon avis tu prends le problème à l'envers : plutôt que de "découper" la chaine selon un pattern, tu devrais rechercher les tags de cette chaine :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	String s = "TOTO id=\"019053695\" type=\"B\" la=\" \" status=\"1\" c=\"HG\" date=\"20071120\"";
     
    	Pattern pattern = Pattern.compile("([a-zA-Z_0-9]+)=\"(.*?)\"");
    	Matcher matcher = pattern.matcher(s);
    	while(matcher.find()) {
    		String name = matcher.group(1);
    		String value = matcher.group(2);
     
    		System.out.printf("%s=[%s]%n", name, value);
    	}
    Explication du pattern : ([a-zA-Z_0-9]+)=\"(.*?)\"
    • ([a-zA-Z_0-9]+) représente le nom du tag. Les parenthèse permettront de le récupérer facilement par la suite (cela défini un groupe).
    • = représente simplement le caractère (pas besoin de le protéger).
    • Enfin \"(.*?)\" signifie : une quote, un nombre quelquonque de caractère suivi d'un autre quote. Le ? qui suit le .* indique qu'il faut recherche la chaine correspondante la plus petite (sinon il englobe tous les tags entre le premier et le dernier)


    Si tu veux gérer les simples quotes (') il faut soit complexifier le pattern, soit effectuer deux passages...


    a++

    PS : Si c'est pour lire du XML, pourquoi ne pas utiliser une des nombreuses librairies faite pour cela ?

  4. #4
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    Grand merci à toi AdiGuba !

    En effet c'est bien la notion de groupe qu'il me manquait pour récupérer ce que je voulais.
    Ton code fonctionne très bien (mise à part le printf que je n'ai pas et que j'ai remplacé par println).

    Pour ce qui est du \022 il s'agit de la valeur héxadécimal du caractère ", ça ne passait pas chez moi de mettre \" mais j'ai du mal m'y prendre puisque ça passe désormais.

    Sinon pour ce qui est d'utiliser un parser java, j'y ai bien pensé seulement le hic c'est que mes fichiers en entrée ne sont pas forcément que du xml, mais aussi du sgml ou d'autres formats plus spécifiques. Du coup si j'utilise un parseur pour du sgml, le parseur risque fortement de planté si le fichier en entré est destructuré (sgml = xml destructuré (pas toujours))
    C'est pour ça que je développe mon propre parseur

    Si toute fois il y a d'autres solutions auxquelles je n'ai pas pensé je suis preneur

    Dans tous les cas merci à toi.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    \022 est un caractère octal et non hexadécimal. La valeur indiquée correspond au caractère hexadécimal \x12. Il n'est donc effectivement pas super valide.

    Pour les apostrophes,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Pattern pattern = Pattern.compile("(\\w+)=(['\"])(.*?)\\2");
    Note :
    • le \\2 indique qu'il faut rechercher la deuxième parenthèse capturante (donc apostrophe ou guillemets droits ici). Les groupes qui te seront intéressants seront donc les 1 et 3 (et non plus 1 et 2).
    • Le groupe \w (échappé \\w) est strictement identique à [a-zA-Z_0-9]. C'est plus court et plus lisible, non ?

  6. #6
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    Ha oui effectivement j'ai lu un peu vite une page web et j'ai confondue valeur octale / héxa.

    Merci pour le \\w qui donne une expression plus lisible c'est vrai.

  7. #7
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par dingoth Voir le message
    • le \\2 indique qu'il faut rechercher la deuxième parenthèse capturante (donc apostrophe ou guillemets droits ici). Les groupes qui te seront intéressants seront donc les 1 et 3 (et non plus 1 et 2).
    Wouah excellent ça

    Je ne connaissait pas et cela peut être vachement utile


  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Ouaip, et encore, si les regex de Java avaient le quart du tiers de la puissance de celles de PERL... ^^

  9. #9
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    J'ai fini par faire un mixte de vos deux regexp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "(\\w+)=['\"](.*?)['\"]"
    Car je ne sais pas pourquoi mais l'utilisation du \\2 dans :
    Pattern pattern = Pattern.compile("(\\w+)=(['\"])(.*?)\\2");
    semble mal fonctionner (mes expression sont mal splittée, ce qui provoque ensuite une exception sur la gestion des valeurs des attributs.

    Merci à vous deux en tout cas

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 252
    Par défaut
    Bah justement... là, tu risques d'avoir pas mal de soucis :-/

    Par exemple si tu as une apostrophe dans un attribut xxx="yyy'zzz", ta regex ne fonctionnera pas car prendra trop peu de caractères : yyy au lieu de yyy'zzz.

    Donc, soit tu utilises la regex
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "(\\w+)=(['\"])(.*?)\\2"
    (la meilleure) soit la regex (moins bonne car ne prend en compte que les guillemets droits), mais certaiment pas un mix des deux.

    Edit : Avec ton texte d'exemple et ma regex, ça fonctionne parfaitement :

    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
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    public class Regex {
    	public static void main (String[] args) {
    		String text = "TOTO id=\'019053695\' type=\"B\" la=\" \" status=\"1\" c=\"HG\" date=\"20071120\"";
    		String regex = "(\\w+)=(['\"])(.*?)\\2";
    		Pattern pattern = Pattern.compile(regex);
    		Matcher matcher = pattern.matcher(text);
    		while(matcher.find()) {
    			String name = matcher.group(1);
    			String value = matcher.group(3);
    			System.out.printf("%s=[%s]%n", name, value);
    		}
    	}
    }
    Résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    id=[019053695]
    type=[B]
    la=[ ]
    status=[1]
    c=[HG]
    date=[20071120]

  11. #11
    kij
    kij est déconnecté
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    362
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 362
    Par défaut
    Mum... tu n'as pas faux c'est vrai.
    C'est peut-être moins permissif mais bien plus sûr, je vais donc garder l'option numéro 1 ^^

    Thanks

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 08/12/2010, 16h49
  2. Comment lire les "Attributes" en XML ?
    Par [ZiP] dans le forum Delphi
    Réponses: 6
    Dernier message: 13/03/2007, 14h33
  3. Parse error à cause d'un tag <?xml
    Par genova dans le forum Langage
    Réponses: 2
    Dernier message: 10/09/2006, 17h00
  4. Constitution de titres en fonction de tags XML
    Par MehdiUSA dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 29/05/2006, 08h55
  5. [C#][xml][regexp] Recherche d'une regexp dans un fichier xml
    Par LeJocker dans le forum Windows Forms
    Réponses: 4
    Dernier message: 18/10/2005, 12h29

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