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

C# Discussion :

Lecture avancée dans un fichier XML volumineux C#


Sujet :

C#

  1. #1
    Membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Octobre 2015
    Messages
    98
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 98
    Points : 59
    Points
    59
    Par défaut Lecture avancée dans un fichier XML volumineux C#
    Bonjour,

    J'ai récupéré un fichier XML open source très volumineux (>30 Mo)

    -Ce fichier va évoluer (re DL régulièrement fonction des mises à jour) donc je ne peut pas faire de conversion en un autre format .
    -Je ne fait dessus que de la lecture (pas d'écriture).
    -Je souhaite un accès rapide par flux sans chargement du fichier XML dans son entier (ou peut être une bonne fois pour toute au démarrage mais sans bouffer la mémoire).

    Que me conseillez-vous comme approche?

    XmlTextreader -> conseil de l'abandonnée au profit de XMLReader
    Xml to Linq -> sympas pour les requêtes mais nécessite de charger la base en entier au préalable (enfin je crois)
    XElement -> idem (enfin je crois)
    Xpath via XmlNodeList pas mal mais j'en chie pour faire mes requêtes...


    le DTD est de cette forme
    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
     
    <!ELEMENT WN (SYNSET+)>
    <!ELEMENT sl.dbxml (SYNSET+)>
    <!ELEMENT SYNSET (STAMP?, ILR*, SUMO*, G_SYN?, ID, SYNONYM, DEF, USAGE*, SNOTE?, BCS?, DOMAIN?, NL*, POS)>
    <!--ELEMENT SYNSET (ID | POS | SYNONYM | ILR | DEF | USAGE | SNOTE | BCS | DOMAIN | NL | SUMO | G_SYN | STAMP)+ -->
    <!ELEMENT ID (#PCDATA)>
    <!ELEMENT POS (#PCDATA)>
    <!ELEMENT SYNONYM (LITERAL | WORD)+>
    <!ELEMENT LITERAL (#PCDATA)>
    <!ATTLIST LITERAL
              lnote CDATA #IMPLIED
              sense CDATA #IMPLIED>
    <!ELEMENT WORD (#PCDATA)>
    <!ELEMENT ILR (#PCDATA)>
    <!ATTLIST ILR
              type CDATA #REQUIRED>
    <!ELEMENT DEF (#PCDATA)>
    <!ELEMENT USAGE (#PCDATA)>
    <!ELEMENT SNOTE (#PCDATA)>
    <!ELEMENT BCS (#PCDATA)>
    <!ELEMENT DOMAIN (#PCDATA)>
    <!ELEMENT NL (#PCDATA)>
    <!ELEMENT SUMO (#PCDATA)>
    <!ATTLIST SUMO
              type CDATA #REQUIRED>
    <!ELEMENT G_SYN (#PCDATA)>
    <!ELEMENT STAMP (#PCDATA)>
    je souhaite des requêtes type :
    -chercher dans le fichier XML, uniquement dans les nœuds LITERAL la valeur "blabla". (la c'est facile)
    -a partir de cette valeur remonte pour atteindre le nœud le plus haut (SYNSET) et récupère son ID (j'arrive a afficher tous ce qui se trouve entre les balises <SYNSET> mais je ne sais pas l'exploiter.)
    -récupère tous ces ID puis trouve la valeur <POS> (la aussi ça va) plus bas dans l'arbre que LITERAL.

    Voila le type de requête. J'ai tester la plupart des options rapidement (j'ai du mal avec les saut de nœud) mais je ne sais laquelle choisir.
    Merci de votre aide.

  2. #2
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 184
    Points : 5 755
    Points
    5 755
    Par défaut
    30Mo c'est tout petit ça
    Charge le en mémoire une fois pour toute.

    Je ne suis pas familier de la représentation "DTD". As tu un extrait de ton xml permettant de faire des tests ?

  3. #3
    Membre expérimenté

    Homme Profil pro
    Responsable des études
    Inscrit en
    Mars 2009
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Responsable des études
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2009
    Messages : 553
    Points : 1 672
    Points
    1 672
    Par défaut
    Hello,

    Vu le type de recherche que tu veux faire, XPath est clairement une bonne solution.

    Tu charges, au choix, ton XML dans une instance de XPathDocument ou de XmlDocument, tu appelles la méthode CreateNavigator() qui te retourne un objet XPathNavigator sur lequel tu peux effectuer tes requêtes.

    Exemple (non testé), pour retrouver tous les éléments LITERAL dont la valeur est "blabla", remonter jusqu'au noeud parent SYNSET et obtenir l'élément ID juste en dessous:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    //LITERAL[.="blabla"]/ancestor::SYNSET/ID

  4. #4
    Membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Octobre 2015
    Messages
    98
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 98
    Points : 59
    Points
    59
    Par défaut
    Bonsoir et merci pour votre aide.

    J'ai un peu chercher de mon coter et j'ai tester du coup la méthode create navigator qui est assez sympas. J'ai un peu de mal avec le type de requête mais ma fois...

    J'ai parcouru beaucoup de (vieux?) post et en filigrane il y'a toujours la fixette de la gourmandise en ressource de tous ces mode de lecture SAUF xmlreader.

    Est-ce que quelqu'un serait me dire ce que l'on entend par la, ou un papier qui en parle? Si 37,8Mo et 117 600 lignes c'est un "petit" fichier XML je me casse clairement la tête pour rien et comme les requêtes Linq je suis plutôt a l'aise je partirai par la (juste question de goût).

    Si effectivement ça consomme beaucoup j'ai pondu un mix entre requête xmlreader et LinQ to XML qui fonctionne bien visiblement mais je suis loin d’être fortiche (j'ai peu être simplement réinventer la roue) .
    Si vous pouvez me dire si vous trouver la démarche cohérente.

    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
     
    XmlReaderSettings setting = new XmlReaderSettings();
                setting.DtdProcessing = DtdProcessing.Parse;
     
                string path = filename;
                using (var loulou = XmlReader.Create(path, setting))
                {
     
                    bool isOnNode = loulou.ReadToDescendant("WN");
                    while (isOnNode)
                    {
                        var element = (XElement)XNode.ReadFrom(loulou);
     
                        var bames = from nm in element.Elements("SYNSET")
                                    where (string)nm.Element("POS") == "n"
                                    select nm;
     
                        foreach (var bame in bames)
                        {
                            Console.WriteLine(bame);
                        }                    
     
                        isOnNode = loulou.ReadToNextSibling("WN");
                    }
                }
    voila encore merci

  5. #5
    Membre du Club
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Octobre 2015
    Messages
    98
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Santé

    Informations forums :
    Inscription : Octobre 2015
    Messages : 98
    Points : 59
    Points
    59
    Par défaut
    J'ai résolu mon soucis.
    Le mot clef était "streaming" ! C'est tout à fait ce que je voulait.
    Donc pour faire du Linq XML sur un flux de données avec xml reader voila un bout de code bien pratique

    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
     
    static IEnumerable<XElement> SimpleStreamAxis(string inputUrl, string matchName)
            {
                XmlReaderSettings settings = new XmlReaderSettings();
                settings.DtdProcessing = DtdProcessing.Parse;
                using (XmlReader reader = XmlReader.Create(inputUrl, settings))
                {
                    reader.MoveToContent();
                    while (reader.Read())
                    {
                        switch (reader.NodeType)
                        {
                            case XmlNodeType.Element:
                                if (reader.Name == matchName)
                                {
                                    XElement el = XElement.ReadFrom(reader)
                                                          as XElement;
                                    if (el != null)
                                        yield return el;
                                }
                                break;
                        }
                    }
                    reader.Close();
                }
            }
    et ensuite dans une méthode quelconque

    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
     
    foreach (string Mot in Mot_Clef)
                {
     
                    // Pour du Regex
                   // string pattern = @"\\b" + Mot + "\\b";                
                   //var reg = new Regex("\\b" + Mot + "\\b", RegexOptions.IgnoreCase);
     
     
     
     
                    Console.WriteLine("################## DU LINQ ##############");
     
                    string inputUrl = filename;
                    IEnumerable<string> bardQuotes = from el in SimpleStreamAxis(inputUrl, "SYNSET")
                                                     where el.Element("SYNONYM").Value.Contains(Mot)
                                                     //where reg.IsMatch(el.Element("SYNONYM").Value)  -> ligne a remplcer pour du Regex
                                                     select (string)el.Element("SYNONYM");
     
     
                    foreach (string str in bardQuotes)
                    {
                        Console.WriteLine("Identifiant : " + str.Trim());
                    }
     
                }
    J'ai laisser le code pour faire du RegEx... Il marche pour une recherche d'une chaine exact dans un string mais pas parfaitement. Je vais post sur ce sujet .

    Encore merci à vous . Ce sujet est résolu

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

Discussions similaires

  1. lecture de valeurs numériques contenues dans un fichier xml
    Par yasse87 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 21/04/2009, 19h13
  2. problème de lecture de é et à dans un fichier xml
    Par taouja dans le forum Format d'échange (XML, JSON...)
    Réponses: 4
    Dernier message: 21/04/2007, 23h43
  3. Problème de lecture dans un fichier xml
    Par Pyra dans le forum Langage
    Réponses: 2
    Dernier message: 18/12/2005, 00h13

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