IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo
Sommaire > Fichiers et données > XML
        Comment lire un fichier Xml avec les classes de l'espace de noms System.Xml.Xpath ?
         Comment créer un XmlNamespaceManager en se basant sur un fichier Xml ?
        Comment sérialiser un objet en XML en ignorant les références circulaires ?



Comment lire un fichier Xml avec les classes de l'espace de noms System.Xml.Xpath ?
auteur : StormimOn
Voici un exemple basique de lecture d'un fichier Xml en se servant non pas de la classe XmlDocument mais des classes de l'espace de noms System.Xml.Xpath. Deux cas sont distingués, les fichiers Xml de base et ceux avec un espace de noms.
1 Fichier Xml basique :

          
<Recordbook>
	<Records>
		<Record>
			<FirstValue>10</FirstValue>
			<SecondValue>51</SecondValue>
		</Record>
		<Record>
			<FirstValue>25</FirstValue>
			<SecondValue>38</SecondValue>
		</Record>
	</Records>
</Recordbook>
        
Son implémentation :

          
		using System.Xml.XPath;
		...
		
        private void TraiteXml()
        {
            XPathDocument doc = new XPathDocument(fileName);
            XPathNavigator nav = doc.CreateNavigator();
            // On récupère un XPathNodeIterator sur les Record
            XPathNodeIterator iter = nav.Select("Recordbook/Records/Record");
            // Pour chaque Record
            while (iter.MoveNext())
            {
                // On récupère l'info FirstValue
                string firstValue = iter.Current.SelectSingleNode("FirstValue").Value;
                // On récupère l'info SecondValue
                string secondValue = iter.Current.SelectSingleNode("SecondValue").Value;
            }
        }

        
2. Fichier Xml avec un espace de noms

          
<?xml version="1.0" encoding="utf-8"?>
<rd:Recordbook xmlns:rd="http://myexemple/myschema/record">
	<rd:Records>
		<rd:Record>
			<rd:FirstValue>10</rd:FirstValue>
			<rd:SecondValue>51</rd:SecondValue>
		</rd:Record>
		<rd:Record>
			<rd:FirstValue>25</rd:FirstValue>
			<rd:SecondValue>38</rd:SecondValue>
		</rd:Record>
	</rd:Records>
</rd:Recordbook>

        
Son implémentation :

          
		using System.Xml;
		using System.Xml.XPath;
		...

        private void TraiteXml()
        {
            XPathDocument doc = new XPathDocument(fileName);
            XPathNavigator nav = doc.CreateNavigator();
            // On ajoute la gestion des espaces de noms
            XmlNamespaceManager mgr = new XmlNamespaceManager
            (nav.NameTable);
            mgr.AddNamespace("rd", "http://myexemple/myschema/record");
            // On récupère un XPathNodeIterator sur les Record
            XPathNodeIterator iter = nav.Select
            ("rd:Recordbook/rd:Records/rd:Record", mgr);
            // Pour chaque Record
            while (iter.MoveNext())
            {
                // On récupère l'info FirstValue
                string firstValue = iter.Current.SelectSingleNode("rd:FirstValue", mgr).Value;
                // On récupère l'info SecondValue
                string secondValue = iter.Current.SelectSingleNode("rd:SecondValue", mgr).Value;
            }
        }


        
Remarque : attention, XPath est sensible à la casse. Le nom des balises doit correspondre exactement.
nav.Select("Recordbook/Records/Record");
et
nav.Select("Recordbook/Records/record");
ne représentent pas la même chose


Comment créer un XmlNamespaceManager en se basant sur un fichier Xml ?
auteur : StormimOn
Précédemment, nous avons vu comment lire un fichier avec les classes XPath. Dans le cas de la présence de namespace dans le fichier Xml, nous avons utilisé la classe XmlNamespaceManager pour gérer ces espace de noms. Le seul défaut c'est que nous alimentions manuellement ces données, nous allons donc maintenant créer ce XmlNamespaceManager de manière automatique.
Fichier Xml utilisé pour l'exemple :

          
<?xml version="1.0" encoding="utf-8"?>
<rd:Recordbook xmlns:rd="http://myexemple/myschema/record">
	<rd:Records>
		<rd:Record>
			<rd:FirstValue>10</rd:FirstValue>
			<rd:SecondValue>51</rd:SecondValue>
		</rd:Record>
		<rd:Record>
			<rd:FirstValue>25</rd:FirstValue>
			<rd:SecondValue>38</rd:SecondValue>
		</rd:Record>
	</rd:Records>
</rd:Recordbook>

        
Son implémentation :

          
		using System.Collections.Generic;
		using System.Xml;
		using System.Xml.XPath;
					...
        private XmlNamespaceManager GetXmlNamespaceManager(XPathNavigator nav)
        {
            XmlNamespaceManager mgr = null;

            nav.MoveToFirstChild();
            foreach (KeyValuePair<string, string> keyPair in nav.GetNamespacesInScope(XmlNamespaceScope.Local))
            {
                if (mgr == null)
                {
                    mgr = new XmlNamespaceManager(nav.NameTable);
                }
                mgr.AddNamespace(keyPair.Key, keyPair.Value);
            }
            nav.MoveToRoot();

            return mgr;
        }

        private void TraiteXml(string fileName)
        {
            XPathDocument doc = new XPathDocument(fileName);
            XPathNavigator nav = doc.CreateNavigator();
            XmlNamespaceManager mgr = GetXmlNamespaceManager(nav);
            if (mgr != null)
            {
                XPathNodeIterator iter = nav.Select("rd:Recordbook/rd:Records/rd:Record", mgr);
                while (iter.MoveNext())
                {
                    string firstValue = iter.Current.SelectSingleNode("rd:FirstValue", mgr).Value;
                    string secondValue = iter.Current.SelectSingleNode("rd:SecondValue", mgr).Value;
                }
            }
        }

        

Comment sérialiser un objet en XML en ignorant les références circulaires ?
auteurs : cardi, tomlev
Prenons le cas d'une classe MaClasse, qui représente un "n?ud" d'une hiérarchie. Chaque n?ud à un parent et des enfants :

          
        public class MaClasse
        {
            public MaClasse()
            {
            	Enfants = new List<MaClasse>();
            }
        
            public MaClasse Parent { get; set; }
            public List<MaClasse> Enfants { get; set; }
        }
        
Dans ce cas de figure, un parent référencera ses enfants, qui eux-même référenceront leur parent : on a donc une référence circulaire, les objets se référencent mutuellement. Si on essaie de sérialiser des objets qui ont des références circulaires, on obtient une erreur à l'exécution.

          
		MaClasse parent = new MaClasse();
		MaClasse enfant1 = new MaClasse();
		MaClasse enfant1 = new MaClasse();

		parent.Enfants.Add(enfant1);
		enfant1.Parent = parent;
		parent.Enfants.Add(enfant2);
		enfant2.Parent = parent;
		
		Serialize(parent);
	
        
Le code ci-dessus génèrera le message d'erreur suivant :
Référence circulaire détectée lors de la sérialisation d'un objet de type ConsoleApplication1.MaClasse.
Afin d'éviter ce problème, il suffit d'ignorer une des références lors de la sérialisation, de façon à ce que les références ne se fassent que dans un sens, en l'occurrence du parent vers les enfants. On va pour cela appliquer l'attribut System.Xml.Serialization.XmlIgnore à la propriété Parent :

          
[XmlIgnore]
public MaClasse Parent { get; set; }

        
lien : fr L'attribut XmlIgnore (tutoriel Developpez.com)
lien : fr System.Xml.Serialization.XmlIgnoreAttribute (MSDN)


Consultez les autres F.A.Q's


Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2010 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.