This article has been localized into Dutch by the community.
Gebruik van XPath met de XmlDocument class
In een vorig hoofdstuk gebruikten we de XmlDocument class om informatie uit een XML bestand te halen. We deden dit via een reeks 'calls' naar de ChildNodes property, hetgeen nogal eenvoudig was omdat het voorbeeld erg eenvoudig was. Het kwam ook niet erg ten goede aan de leesbaarheid van onze code. Dus in dit hoofdstuk kijken we naar een andere benadering, die zonder meer krachtiger is en toch beter te lezen en te onderhouden is. De technologie die we zullen gebruiken heet XPath en wordt onderhouden door dezelfde organisatie die de XML standaard ontwikkelde. XPath is in feite een volledige query taal met vele mogelijkheden. Maar omdat dit niet een XPath tutorial is, bekijken we alleen maar een paar basale queries. Maar zelfs in zijn simpelste vorm is XPath nog altijd krachtig, zoals je gaat zien in de volgende voorbeelden.
De XmlDocument class heeft diverse methods die een XPath query als parameter nemen en de resulterende XmlNode(s) retourneren. In dit hoofdstuk kijken we naar twee methods: De SelectSingleNode() method, die één enkele XmlNode retourneert volgens de XPath query, en de SelectNodes() method, die een XmlNodeList collectie van XmlNode objects retourneert volgens de XPath query.
We zullen beide bovengenoemde methods gebruiken, maar in plaats van de valuta informatie XML die we eerder getest hebben, proberen we nu een nieuwe XML bron. RSS feeds zijn in essentie XML documenten die op een specifieke manier gebouwd zijn om het mogelijk te maken dat een hele vracht nieuws readers kunnen parsen en op hun eigen manier de informatie laten zien.
We gebruiken een RSS 'feed' van CNN, op locatie http://rss.cnn.com/rss/edition_world.rss, met nieuws van over de hele wereld. Als je dat opent in je browser, laat je browser dat mogelijk op een plezierige manier zien, waardoor je een overzicht krijgt van het aanbod en je erop gaat abonneren, maar laat je daarvoor niet voor de gek houden: Onder de motorkap is het gewoon XML, wat je te zien krijgt als je in je browser "Paginabron bekijken" kiest. Je zult zien dat het root element 'rss' heet. Het rss element heeft doorgaans één of meerdere 'channel' elementen, en binnen elk element kunnen we informatie vinden zowel over de 'feed' als over de 'item' nodes, die de nieuws items zijn zie we willen zien.
In het volgende voorbeeld gebruiken we de SelectSingleNode() method om de titel van de feed te krijgen. Als je naar de XML kijkt, zie je dat er een <title> element is als 'child' element van het <channel> element, wat weer een child element is van het <rss> element, de root. Die query kan als volgt beschreven worden in XPath:
//rss/channel/title
We schrijven gewoon de naam van het element waar we naar zoeken, gescheiden met een forward-slash (/), die aangeeft dat het element een 'child' moet zijn van het element vóór de voorafgaande forward-slash. Het gebruik van dit XPath is zo simpel als dit:
using System;
using System.Text;
using System.Xml;
namespace ParsingXml
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNode titleNode = xmlDoc.SelectSingleNode("//rss/channel/title");
if(titleNode != null)
Console.WriteLine(titleNode.InnerText);
Console.ReadKey();
}
}
}
We gebruiken de SelectSingleNode() method om het <title> element te localiseren, die gewoon ons XPath als een string parameter gebruikt. Daarna checken we om er zeker van de te zijn dat er een resultaat geretourneerd is, en zo ja, dan drukken we de InnerText af van de gelocaliseerde node, wat de titel van de RSS feed zou moeten zijn.
In het volgende voorbeeld gebruiken we de SelectNode() method om alle item nodes in de RSS feed te vinden en dan informatie erover af te drukken:
using System;
using System.Text;
using System.Xml;
namespace ParsingXml
{
class Program
{
static void Main(string[] args)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNodeList itemNodes = xmlDoc.SelectNodes("//rss/channel/item");
foreach(XmlNode itemNode in itemNodes)
{
XmlNode titleNode = itemNode.SelectSingleNode("title");
XmlNode dateNode = itemNode.SelectSingleNode("pubDate");
if((titleNode != null) && (dateNode != null))
Console.WriteLine(dateNode.InnerText + ": " + titleNode.InnerText);
}
Console.ReadKey();
}
}
}
De SelectNodes() method neemt een XPath query als string, net zoals in het vorige voorbeeld, en retourneert dan een lijst met XmlNode objects in een XmlNodeList collectie. We itereren er doorheen met een foreach lus, en van elk van de item nodes vragen we een child node met de naam titel en pubDate (datum van publicatie) waarbij we de SelectSingleNode() rechtstreeks op de item node gebruiken. Als we ze allebei hebben, printen we de datum en de titel op dezelfde regel en gaan door.
In ons voorbeeld wilden we twee verschillende waarden uit elke item node. En daarom juist vroegen we naar de item nodes en verwerkten elk ervan. Echter, als we alleen maar bv. de titels van elk item wilden, dan konden we de XPath query veranderen in zoiets als dit:
//rss/channel/item/title
Het matcht met elke titel node van de item nodes. Hier is de query met wat C# code om het allemaal te laten gebeuren:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("http://rss.cnn.com/rss/edition_world.rss");
XmlNodeList titleNodes = xmlDoc.SelectNodes("//rss/channel/item/title");
foreach(XmlNode titleNode in titleNodes)
Console.WriteLine(titleNode.InnerText);
Console.ReadKey();