web-dev-qa-db-fra.com

Comment gérer XML en C #

Quelle est la meilleure façon de traiter les documents XML, XSD, etc. en C # 2.0? 

Quelles classes utiliser, etc. Quelles sont les meilleures pratiques d'analyse et de création de documents XML, etc. 

EDIT: Les suggestions .Net 3.5 sont également les bienvenues.

79

Le moyen principal de lecture et d'écriture en C # 2.0 est effectué via la classe XmlDocument . Vous pouvez charger la plupart de vos paramètres directement dans XmlDocument via XmlReader qu'il accepte.

Chargement de XML directement

XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");

Chargement de XML à partir d'un fichier

XmlDocument document = new XmlDocument();
document.Load(@"C:\Path\To\xmldoc.xml");
// Or using an XmlReader/XmlTextReader
XmlReader reader = XmlReader.Create(@"C:\Path\To\xmldoc.xml");
document.Load(reader);

Je trouve que le moyen le plus simple et le plus rapide de lire un document XML consiste à utiliser XPath.

Lecture d'un document XML à l'aide de XPath (Utilisation de XmlDocument qui nous permet d'éditer)

XmlDocument document = new XmlDocument();
document.LoadXml("<People><Person Name='Nick' /><Person Name='Joe' /></People>");

// Select a single node
XmlNode node = document.SelectSingleNode("/People/Person[@Name = 'Nick']");

// Select a list of nodes
XmlNodeList nodes = document.SelectNodes("/People/Person");

Si vous devez utiliser des documents XSD pour valider un document XML, vous pouvez l'utiliser.

Validation de documents XML sur des schémas XSD

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd

XmlReader reader = XmlReader.Create(pathToXml, settings);
XmlDocument document = new XmlDocument();

try {
    document.Load(reader);
} catch (XmlSchemaValidationException ex) { Trace.WriteLine(ex.Message); }

Validation de XML contre XSD à chaque Node (UPDATE 1)

XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidateType = ValidationType.Schema;
settings.Schemas.Add("", pathToXsd); // targetNamespace, pathToXsd
settings.ValidationEventHandler += new ValidationEventHandler(settings_ValidationEventHandler);

XmlReader reader = XmlReader.Create(pathToXml, settings);
while (reader.Read()) { }

private void settings_ValidationEventHandler(object sender, ValidationEventArgs args)
{
    // e.Message, e.Severity (warning, error), e.Error
    // or you can access the reader if you have access to it
    // reader.LineNumber, reader.LinePosition.. etc
}

Écrire un document XML (manuellement)

XmlWriter writer = XmlWriter.Create(pathToOutput);
writer.WriteStartDocument();
writer.WriteStartElement("People");

writer.WriteStartElement("Person");
writer.WriteAttributeString("Name", "Nick");
writer.WriteEndElement();

writer.WriteStartElement("Person");
writer.WriteStartAttribute("Name");
writer.WriteValue("Nick");
writer.WriteEndAttribute();
writer.WriteEndElement();

writer.WriteEndElement();
writer.WriteEndDocument();

writer.Flush();

(UPDATE 1)

Dans .NET 3.5, vous utilisez XDocument pour effectuer des tâches similaires. Cependant, la différence est que vous avez l’avantage d’effectuer des requêtes Linq pour sélectionner les données exactes dont vous avez besoin. Avec l'ajout d'initialiseurs d'objet, vous pouvez créer une requête qui retourne même des objets de votre propre définition directement dans la requête elle-même.

    XDocument doc = XDocument.Load(pathToXml);
    List<Person> people = (from xnode in doc.Element("People").Elements("Person")
                       select new Person
                       {
                           Name = xnode.Attribute("Name").Value
                       }).ToList();

(UPDATE 2)

Une manière intéressante de .NET 3.5 consiste à utiliser XDocument pour créer du XML ci-dessous. Cela fait apparaître le code selon un modèle similaire à la sortie souhaitée.

XDocument doc =
        new XDocument(
              new XDeclaration("1.0", Encoding.UTF8.HeaderName, String.Empty),
              new XComment("Xml Document"),
              new XElement("catalog",
                    new XElement("book", new XAttribute("id", "bk001"),
                          new XElement("title", "Book Title")
                    )
              )
        );

crée

<!--Xml Document-->
<catalog>
  <book id="bk001">
    <title>Book Title</title>
  </book>
</catalog>

Tout le reste échoue, vous pouvez consulter cet article MSDN qui contient de nombreux exemples dont j'ai déjà parlé et bien plus encore. http://msdn.Microsoft.com/en-us/library/aa468556.aspx

173
nyxtom

Cela dépend de la taille; pour les xml de taille petite à moyenne, un DOM tel que XmlDocument (toutes versions C #/.NET) ou XDocument (.NET 3.5/C # 3.0) est le gagnant évident. Pour utiliser xsd, vous pouvez charger xml avec un XmlReader , et un XmlReader accepte (de Créer ) un XmlReaderSettings . Les objets XmlReaderSettings ont une propriété Schemas qui peut être utilisée pour effectuer une validation xsd (ou dtd).

Pour l'écriture XML, les mêmes choses s'appliquent, notant qu'il est un peu plus facile de mettre en forme le contenu avec LINQ-to-XML (XDocument) que l'ancien XmlDocument.

Toutefois, pour les fichiers XML volumineux, un DOM peut traiter trop de mémoire, auquel cas vous devrez peut-être utiliser directement XmlReader/XmlWriter.

Enfin, pour manipuler XML, vous souhaiterez peut-être utiliser XslCompiledTransform (un calque xslt).

L'alternative au travail avec XML est de travailler avec un modèle d'objet; vous pouvez utiliser xsd.exe pour créer des classes représentant un modèle conforme à xsd, et simplement charger xml as objects, le manipuler avec OO, puis sérialiser à nouveau ces objets; vous faites cela avec XmlSerializer .

29
Marc Gravell

la réponse de nyxtom est très bonne. J'ajouterais quelques éléments à cela:

Si vous avez besoin d'un accès en lecture seule à un document XML, XPathDocument est un objet beaucoup plus léger que XmlDocument

L'inconvénient de l'utilisation de XPathDocument est que vous ne pouvez pas utiliser les méthodes SelectNodes et SelectSingleNode bien connues de XmlNode. A la place, vous devez utiliser les outils fournis par IXPathNavigable: utilisez CreateNavigator pour créer une XPathNavigator et utilisez XPathNavigator pour créer XPathNodeIterators afin de parcourir les listes de nœuds trouvées via XPath. Cela nécessite généralement quelques lignes de code de plus que les méthodes XmlDocument.

Mais: les classes XmlDocument et XmlNode implémentent IXPathNavigable, ainsi tout code que vous écrivez pour utiliser ces méthodes sur une XPathDocument fonctionnera également sur une XmlDocument. Si vous vous habituez à écrire contre IXPathNavigable, vos méthodes peuvent fonctionner avec l'un ou l'autre objet. (C’est pourquoi l’utilisation de XmlNode et XmlDocument dans les signatures de méthodes est marquée par FxCop.)

Malheureusement, XDocument et XElement (et XNode et XObject) n'implémentent pas IXPathNavigable.

Une autre chose absente de la réponse de nyxtom est XmlReader. Vous utilisez généralement XmlReader pour éviter la surcharge liée à l'analyse du flux XML dans un modèle objet avant de commencer à le traiter. A la place, vous utilisez une variable XmlReader pour traiter le noeud d'entrée du flux d'entrée à la fois. C’est essentiellement la réponse de .NET à SAX. Il vous permet d’écrire du code très rapide pour traiter des documents XML très volumineux. 

XmlReader fournit également le moyen le plus simple de traiter des fragments de document XML, par exemple. le flux d'éléments XML sans élément englobant renvoyé par l'option FOR XML RAW de SQL Server.

Le code que vous écrivez en utilisant XmlReader est généralement très étroitement lié au format du XML qu'il lit. L'utilisation de XPath permet à votre code d'être couplé beaucoup plus librement au XML, raison pour laquelle il s'agit généralement de la bonne réponse. Mais lorsque vous devez utiliser XmlReader, vous en avez vraiment besoin.

12
Robert Rossney

101 échantillons de Linq 

http://msdn.Microsoft.com/en-us/library/bb387098.aspx

et exemples Linq to XML

http://msdn.Microsoft.com/en-us/vbasic/bb688087.aspx

Et je pense que Linq rend XML facile.

4
emremp

Tout d'abord, familiarisez-vous avec les nouvelles classes XDocument et XElement , car elles constituent une amélioration par rapport à la famille précédente de XmlDocument. 

  1. Ils travaillent avec LINQ 
  2. Ils sont plus rapides et plus légers

Cependant , il se peut que vous deviez quand même utiliser les anciennes classes pour travailler avec du code hérité, notamment les proxies précédemment générés. Dans ce cas, vous devrez vous familiariser avec certains modèles d'interopérabilité entre ces classes de traitement XML.

Je pense que votre question est assez large et qu’il faudrait trop de réponses dans une seule réponse pour donner des détails, mais c’est la première réponse générale à laquelle je pensais, et sert de point de départ.

4
hurst

Si vous travaillez dans .NET 3.5 et que vous n'avez pas peur du code expérimental, vous pouvez vérifier LINQ to XSD ( http://blogs.msdn.com/xmlteam/archive/2008/02/21/linq- to-xsd-alpha-0-2.aspx ) qui générera des classes .NET à partir d'un XSD (y compris les règles intégrées du XSD).

Il est ensuite en mesure d'écrire directement dans un fichier et de le lire à partir d'un fichier en s'assurant qu'il est conforme aux règles XSD.

Je suggère définitivement d'avoir un XSD pour tout document XML avec lequel vous travaillez:

  • Vous permet d'appliquer des règles dans le XML
  • Permet aux autres de voir comment le XML est/sera structuré
  • Peut être utilisé pour la validation de XML

Je trouve que Liquid XML Studio est un excellent outil pour générer des fichiers XSD. C'est gratuit!

2
Aaron Powell

Mon opinion personnelle, en tant que programmeur C #, est que le meilleur moyen de gérer XML en C # est de déléguer cette partie du code à un projet VB .NET. Dans .NET 3.5, VB .NET possède des littéraux XML, ce qui rend l'utilisation de XML beaucoup plus intuitive. Voir ici, par exemple:

Présentation de LINQ to XML dans Visual Basic

(Veillez à configurer la page pour afficher le code VB, pas le code C #.)

J'écrirais le reste du projet en C #, mais gérerais le XML dans un projet référencé VB.

1
Ryan Lundy

Écrire du XML avec la classe XmlDocument 

//itemValues is collection of items in Key value pair format
//fileName i name of XML file which to creatd or modified with content
    private void WriteInXMLFile(System.Collections.Generic.Dictionary<string, object> itemValues, string fileName)
    {
        string filePath = "C:\\\\tempXML\\" + fileName + ".xml";
        try
        {

            if (System.IO.File.Exists(filePath))
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filePath);                   

                XmlNode rootNode = doc.SelectSingleNode("Documents");

                XmlNode pageNode = doc.CreateElement("Document");
                rootNode.AppendChild(pageNode);


                foreach (string key in itemValues.Keys)
                {

                    XmlNode attrNode = doc.CreateElement(key);
                    attrNode.InnerText = Convert.ToString(itemValues[key]);
                    pageNode.AppendChild(attrNode);
                    //doc.DocumentElement.AppendChild(attrNode);

                }
                doc.DocumentElement.AppendChild(pageNode);
                doc.Save(filePath);
            }
            else
            {
                XmlDocument doc = new XmlDocument();
                using(System.IO.FileStream fs = System.IO.File.Create(filePath))
                {
                    //Do nothing
                }

                XmlNode rootNode = doc.CreateElement("Documents");
                doc.AppendChild(rootNode);
                doc.Save(filePath);

                doc.Load(filePath);

                XmlNode pageNode = doc.CreateElement("Document");
                rootNode.AppendChild(pageNode);

                foreach (string key in itemValues.Keys)
                {                          
                    XmlNode attrNode = doc.CreateElement(key);                           
                    attrNode.InnerText = Convert.ToString(itemValues[key]);
                    pageNode.AppendChild(attrNode);
                    //doc.DocumentElement.AppendChild(attrNode);

                }
                doc.DocumentElement.AppendChild(pageNode);

                doc.Save(filePath);

            }
        }
        catch (Exception ex)
        {

        }

    }

OutPut look like below
<Dcouments>
    <Document>
        <DocID>01<DocID>
        <PageName>121<PageName>
        <Author>Mr. ABC<Author>
    <Dcoument>
    <Document>
        <DocID>02<DocID>
        <PageName>122<PageName>
        <Author>Mr. PQR<Author>
    <Dcoument>
</Dcouments>
1
Anil Rathod

Si vous créez un ensemble de données typé dans le concepteur, vous obtenez automatiquement un xsd, un objet fortement typé, et pouvez charger et enregistrer le xml avec une ligne de code.

1
Peter C

Si vous avez besoin de convertir des données entre XmlNode <=> XNode <=> XElement
(par exemple pour utiliser LINQ) ces extensions peuvent vous être utiles:

public static class MyExtensions
{
    public static XNode GetXNode(this XmlNode node)
    {
        return GetXElement(node);
    }

    public static XElement GetXElement(this XmlNode node)
    {
        XDocument xDoc = new XDocument();
        using (XmlWriter xmlWriter = xDoc.CreateWriter())
            node.WriteTo(xmlWriter);
        return xDoc.Root;
    }

    public static XmlNode GetXmlNode(this XElement element)
    {
        using (XmlReader xmlReader = element.CreateReader())
        {
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(xmlReader);
            return xmlDoc;
        }
    }

    public static XmlNode GetXmlNode(this XNode node)
    {
        return GetXmlNode(node);
    }
}

Usage:

XmlDocument MyXmlDocument = new XmlDocument();
MyXmlDocument.Load("MyXml.xml");
XElement MyXElement = MyXmlDocument.GetXElement(); // Convert XmlNode to XElement
List<XElement> List = MyXElement.Document
   .Descendants()
   .ToList(); // Now you can use LINQ
...
0
Michael Hutter

La réponse de Cookey est bonne ... mais voici des instructions détaillées sur la création d'un objet fortement typé à partir d'un fichier XSD (ou XML) et la sérialisation/désérialisation en quelques lignes de code:

Instructions

0
Steve Horn

nyxtom,

"Doc" et "xdoc" ne devraient-ils pas correspondre dans l'exemple 1?

XDocument **doc** = XDocument.Load(pathToXml);
List<Person> people = (from xnode in **xdoc**.Element("People").Elements("Person")
                   select new Person
                   {
                       Name = xnode.Attribute("Name").Value
                   }).ToList();
0
mokumaxCraig