XML et CSharp

De Banane Atomic
Révision datée du 16 octobre 2018 à 11:25 par Nicolas (discussion | contributions) (→‎Requête XPath indifférente à la casse)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à la navigationAller à la recherche

XDocument (Linq to XML)

XmlDocument (DOM)

Lecture

Construit un modèle objet du document xml.

Xml.svg
<?xml version="1.0" encoding="utf-8"?>
<racine>
	<noeudparent attribut="1">
		<noeudfils>10</noeudfils>
		<noeudfils>20</noeudfils>
	</noeudparent>
</racine>
Csharp.svg
XmlDocument doc = new XmlDocument();
doc.Load(path); // doc.InnerXml → tous le contenu du document xml
// NodeType → Document    |    BaseURI → chemin complet vers le fichier xml

// Nœud racine du document → racine :
XmlElement racine = doc.DocumentElement;  // XmlElement hérite de XmlNode
// InnerXml → tous les noeuds et sous-noeuds fils du noeud courant.
// OutterXml → le noeud courant plus tous les noeuds et sous-noeuds fils du noeud courant.

XmlNode noeudParent = doc.SelectSingleNode("racine/noeudparent");
// Name → noeudparent    |    NodeType → Element
// InnerXml → <noeudfils>10</noeudfils><noeudfils>20</noeudfils>
// OutterXml → <noeudparent attribut="1">...</noeudparent>
// InnerText → 1020

XmlAttribute attribut = noeudParent.Attributes[0];
XmlAttribute attribut = noeudParent.Attributes["attribut"];
// Value → 1    |    Name → attribut

XmlNode noeudFils = noeudParent.SelectSingleNode("noeudfils");
// Name → noeudfils    |    NodeType → Element
// InnerXml → 10    |    OutterXml → <noeudfils>10</noeudfils>
// InnerText → 10

XmlNode contenu = noeudFils.FirstChild;
// NodeType → Text    |    Value → 10

Écriture

Permet la modification de certains éléments du fichier xml.

Csharp.svg
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlElement ElementRacine = doc.DocumentElement;

XmlElement element = doc.CreateElement("Contact");
XmlAttribute nameAttribut = doc.CreateAttribute("Name");
nameAttribut.Value = c.nom;
element.Attributes.Append(nameAttribut);

XmlNode nodeContact = ElementRacine.AppendChild(element);
doc.Save(path);

DataSet

Lecture

Le DataSet est une représentation en mémoire des données provenant du fichier xml.

Csharp.svg
var ds = new DataSet();

// depuis un fichier XML
ds.ReadXml(@"C:\file.xml");

// depuis un String
var xmlTexte = "<root><elt><col1>111</col1><col2>222</col2></elt><elt><col1>333</col1><col2>444</col2></elt></root>";
ds.ReadXml(new StringReader(xmlTexte));

Écriture

Csharp.svg
// dans un String
var xmlContent = new StringWriter();
ds.WriteXml(xmlContent);

// dans un fichier
ds.WriteXml(@"C:\Content.xml");

XmlReader (SAX)

Lecture

Lis le document ligne par ligne indépendamment de la structure xml.

Csharp.svg
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
    var reader = XmlReader.Create(stream);

    while (reader.Read())
    {
        // On attrape la première balise Nœud
        if (reader.NodeType == XmlNodeType.Element && reader.Name == "Noeud")
        {
            string tel = reader.GetAttribute("Number");
            string message = reader.ReadElementContentAsString();

            // sous-éléments
            int eventDepth = reader.Depth;
            reader.Read();
            while (reader.Depth > eventDepth)
            {
                if (reader.MoveToContent() == XmlNodeType.Element)
                {
                    switch (reader.Name)
                    {
                        case "SousNoeud":
                            string sousMessage = reader.ReadElementContentAsString();
                            break;
                    }
                }

                reader.Read();

Écriture StreamWriter

Écris le fichier ligne par ligne et écrase le contenu précédemment existant. Idéal pour la création d’un nouveau fichier.

Csharp.svg
StreamWriter monStreamWriter = new StreamWriter(path);
monStreamWriter.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>");
monStreamWriter.WriteLine("<ROOT>");
monStreamWriter.WriteLine("</ROOT>");
monStreamWriter.Close();

Erreurs

'...' is an undeclared prefix.

Csharp.svg
// une des solution est d'ignorer les namespaces
var reader = new XmlTextReader(stream) { Namespaces = false };

Multiple root elements

Csharp.svg
var settings = new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment };
var reader = XmlReader.Create(stream, settings);

undeclared prefix and multiple root elements

Csharp.svg
var settings = new XmlReaderSettings() {
    NameTable = new NameTable(),
    ConformanceLevel = ConformanceLevel.Fragment
};
var nsmgr = new XmlNamespaceManager(settings.NameTable);
nsmgr.AddNamespace("MyNamespace", "http://domain.com");
var context = new XmlParserContext(null, nsmgr, null, XmlSpace.Default, Encoding.UTF8);
var reader = XmlReader.Create(stream, settings, context);

XPath

Csharp.svg
// Sélectionne tous les noeuds correspondant à la requête
XmlNodeList nodes = xmlDocument.SelectNodes("requête XPATH");

// Sélectionne le premier noeud correspondant à la requête
XmlNode node = xmlDocument.SelectSingleNode("requête XPATH");

Localisation du noeud

/ Le nœud fictif, dit « root element », qui englobe tout le document sauf <?xml version="1.0"?>
/xXx Le noeud xXx racine du document
//xXx Tous les noeuds xXx du document
//xXx/yYy Tous les noeuds yYy fils d'un noeud xXx
../xXx Tous les noeuds xXx parent du noeud courant
//xXx/* Tous les noeuds fils d'un noeud xXx
//xXx/parent::* Tous les noeuds parent direct d'un noeud xXx
//xXx/following-sibling::* Tous les noeuds frère (de même niveau) qui viennent après xXx
//xXx/preceding-sibling::* Tous les noeuds frère (de même niveau) qui viennent avant xXx

Combinaisons

xXx | yYy Tous les noeuds xXx et yYy fils du noeud courant

Conditions

xXx[1] Le premier noeud xXx fils du noeud courant
xXx[last()] Le dernier noeud xXx fils du noeud courant
xXx[child="Text"] Sélectionne les nœuds xXx qui ont au moins un enfant child dont le contenu textuel (string-value) est Text
xXx[text()="Text"] Sélectionne les nœuds xXx dont le contenu textuel (string-value) est Text
//*[starts-with(name(),'x')] Tous les noeuds qui commencent par x
//*[contains(name(),'x')] Tous les noeuds qui contiennent x

Attributs

//@aAa Sélectionne tous les attributs aAa du document
//xXx[@*] Sélectionne tous les nœuds xXx ayant au moins un attribut
//xXx[not(@*)] Sélectionne tous les nœuds xXx n'ayant pas d'attributs
//xXx[@aAa='value'] Sélectionne tous les nœuds xXx ayant un attribut aAa de valeur value
//xXx[normalize-space(@aAa)='value'] Sélectionne tous les nœuds xXx ayant un attribut aAa de valeur value.
Les espaces de début et de fin sot ignorés lors de la comparaison.
//xXx[starts-with(@aAa, 'f')] Sélectionne tous les nœuds xXx ayant un attribut aAa dont la valeur commence par f

Fonctions

name() Le nom du noeud courant
translate(original,old,new) Modifie original en remplacent les caractères contenus dans old par ceux contenus dans new

Requête XPath indifférente à la casse

On peut utiliser la méthode translate pour passer en minuscule tous les noms des noeuds

Cs.svg
// recherche tous les noeuds ''xxx'' quelque soit leur casse (xxx, Xxx, xXx, xxX, XXx, XxX, xXX, XXX)
xmlDocument.SelectSingleNode("*[translate(name(),'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='xxx']");

Texte entre deux balises

Xml.svg
<node>texte</node>
Csharp.svg
// lecture :
node.FirstChild.Value;
// écriture :
XmlText xmlText = xmlDoc.CreateTextNode("texte");
node.AppendChild(xmlText);

Erreurs

Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function

Les namespaces du document XML doivent être ajoutés au XmlNamespaceManager, et celui-ci utilisé lors des requêtes XPath.

Csharp.svg
var document = new XmlDocument();
var nsmgr = new XmlNamespaceManager(document.NameTable);
nsmgr.AddNamespace("xsl", "http://www.w3.org/1999/XSL/Transform");

var node = deliveryFile.SelectSingleNode("/xsl:Node/Node", nsmgr);