Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Julien Chable

He blogs, you blog, I blog ...

Archives

[Open XML] Travailler avec Open XML : Linq To XML (Partie 2 - Requêtes/XPath)

Suite au dernier post, voici la suite qui traitera de XPath et des requêtes. Contrairement au post d’introduction, l’ensemble des exemples s’appliqueront maintenant à des documents Open XML (puisque c’est un domaine dans lequel les espaces de noms et les structures sont relativement complexes).

Pour rappel, Linq to XML permet de créer, manipuler du XML de façon intuitive et en un minimum de lignes de code. Par exemple, ici pour générer du RSS en moins de 1 minute (comparer au temps qu’un vous faut pour faire des Append de XmlElement …) :

XDocument doc = new XDocument(
    new XDeclaration("1.0", "utf-8", "yes"),
    new XComment("Ma feed !"),
    new XElement("rss", 
        new XAttribute("version", "2.0"),
        new XElement ("channel",
            new XElement("title", "Le blog de Julien Chable"),
            new XElement("description", "Le blog de Julien Chable sur le standards, l’interop, Open XML and much more."),
            new XElement("link", http://blogs.developpeur.org/neodante),
            new XElement("item",
                new XElement("title", "Coucou"),
                new XElement("description", "COucou super description"),
                new XElement("pubDate", DateTime.Now.ToUniversalTime()),
                new XElement("guid", Guid.NewGuid())),
            new XElement("item",
                new XElement("title", "Coucou 2"),
                new XElement("description", "Coucou 2 super description"),
                new XElement("pubDate", DateTime.Now.ToUniversalTime()),
                new XElement("guid", Guid.NewGuid()))
            )
        )
     );

Utiliser les requêtes Linq pour requêter une structure XML

Pour ceux qui connaissent un minimum XPath (notamment les personnes qui font du XSLT), vous savez qu’il existe la notion “d’axe”. Un axe permet de créer une requête dans une direction précise : vers ses ancêtres, ses enfants, ses fères/soeurs, ses descendants, etc …

En réalité Linq est similaire à XPath à plus d’un titre, il est aussi différent sur d’autres points. MSDN fourni un article intéressant à ce sujet, qui vous expliquera bien mieux que ce post, les similitudes et les différences au niveau des axes et d’un tas d’autres choses : http://msdn.microsoft.com/en-us/library/bb675156.aspx. Vous trouverez également de nombreux exemples XPath/Linq to XML à cette adresse : http://msdn.microsoft.com/en-us/library/bb675178.aspx.

En fait pour requêter une structure XML, vous avez 2 façons de le faire et 3 syntaxes au final :

  • Utiliser les instructions Linq (from, select, …) directement dans votre code :
    // Récupère tous les paragraphes d’un document
    var paragraphs = from p in doc.Descendants(w + "p") select p;
  • Utiliser les méthodes d’extension (similaire au précédent point) :
  • // Récupère tous les paragraphes d’un document
    var paragraphs = doc.Descendants(w + "p");

  • Utiliser XPath et les méthodes d’extension de System.Xml.XPath : ‘/w:document/w:body/w:p’ ou ‘//w:p’

Le choix entre le point 1 et 2 est juste une question de goût, et personnellement je les utilise en fonction des situations. Comme vous pouvez le constater il est aisé de se déplacer dans l’arbre XML avec les méthodes de la classe XElement imite le comportement de XPath en spécifiant des axes de requêtes et en les cumulant.

Par exemple pour trouver toutes les formes d'une diapositive PresentationML :

foreach (XElement sp in diapDoc.Root
                .Element(p + "cSld").Element(p + "spTree").Elements(p + "sp"))

La requête précédente revient à une requête XPath ‘/p:cSld/p:spTree/p:sp’. Nous aurions très bien pu créer une requête de la forme pour aller plus vite me direz vous :

foreach (XElement sp in diapDoc.Root.Descendants(p + "sp"))

Cependant la requête XPath vaudrait ‘//p:sp’ ou ‘/descendant-or-self::p:sp’, ce qui n’est pas forcément ce que l’on voudrait puisque si d’autres éléments <p:sp> du même espace de nom existe à d’autres emplacements dans la structure, il vous seront également retournés.

Utilisation de XPath

Naviguer et requêter avec les méthodes ou les instructions Linq est réellement simple mais quelquefois par simplicité vous aurez besoin de XPath afin de spécifier des conditions ou des expressions qui ne seraient que trop compliquées à réaliser en Linq to XML

Tout d’abord n’oubliez pas d’ajouter l’import de l’espace de nom .NET : System.Xml.XPath; Cela vous donnera accès à 3 méthodes d’extension qui vous servirons bien :

image

Pour récupérer un identifiant de propriétés (héritage slide –> layout –> master) dans PresentationML :

XElement phLayout = layoutDoc.XPathSelectElement(
                    String.Format("//p:sp/p:nvSpPr/p:nvPr/p:ph[@idx={0}]",
                    phElem.Attribute("idx").Value), ...);

Néanmoins, ces méthodes d’extension XPath utilise du vieux pour faire du neuf et si votre structure comporte un espace de nom (en plus de celui par défaut), il va vous falloir comme “à l’ancienne'” utiliser un XmlNamespaceManager (d’où le … à la fin du précédent exemple).

Par exemple pour récupérer tous les éléments de texte de l’avant dernier paragraphe d’un document WordprocessingML :

MainDocumentPart mainPart = wordDoc.MainDocumentPart;
XmlReader reader = XmlTextReader.Create(mainPart.GetStream());
XmlNamespaceManager nsManager = new XmlNamespaceManager(reader.NameTable);
nsManager.AddNamespace("w", w.NamespaceName);
XDocument doc = XDocument.Load(reader);
var pars = doc.XPathSelectElements("//w:p[position()=last()-1]//w:t", nsManager);
foreach (var par in pars)
{
          Console.WriteLine(par.ToString());
}

C’est ici que cet article s’arrête, en effet celui n’a pas pour but de présenter Linq to XML, mais son application dans le monde Open XML. Je pense vous avoir convaincu que si vous avez l’occasion d’utiliser .NET 3.5 dans vos projets, la puissance de Linq To XML vous permettra de gagner beaucoup de temps à générer ou manipuler le contenu de vos documents XML.

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: mardi 8 juillet 2008 01:05 par neodante
Classé sous : ,

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01