As mentioned already, all the child nodes of an element are stored in an array. In fact, if you pass the name of the root as your XPath expression, this is equivalent to applying [1] to it. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos[1]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.InnerXml,
"Video Collection",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
By using arrays, the XPath language makes it possible to get a collection of nodes based on their common name. To get only the nodes that have a specific section, pass the name of that section to the square brackets of the parent element. From our XML document, imagine you want only the videos that have a section named cast-members. Here is an example of getting them: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video[cast-members]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(string.Format("Video --------------------------------------------------------------------\n{0}",
xnVideo.OuterXml),
"Videos that have a cast-members section",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
This would produce:
Notice that, in our XML document, only some of the videos include the list of actors. If you pass a name that doesn't exist, the interpreter would produce an empty result (no exception would be thrown).
Considering the following XPath expression: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video/cast-members[actor]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
This would produce all cast-members sections of all videos (only the cast-members section). If you want to get a only a specific child node, assign its value to the name in the square brackets. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video/cast-members[actor = 'Penelope Ann Miller']");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
Based on our XML document, the result would produce only the cast-members sections that include Penelope Ann Miller.
After accessing a node by name, if it has at least one child node, you can access it/them by passing its/their name after the parent and /. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video[categories]/keywords");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
If you want to locate a specific child node, in the square brackets, type .= and the value of the node. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video/cast-members/actor[. = 'Eddie Murphy']");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.InnerText,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
To get only the parent nodes that have child nodes that in turn have certain child nodes, in the square brackets, type the names of the child node and grand-child separated by /. Here an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video[categories/keywords]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
From our XML file, this would produce only the videos that have a categories section but that categories section must have a keywords section as child, which excludes a video where the categories and their keywords are children on the same level:
Notice that our XML document has some videos that have a cast-members section. Instead of getting all of them, you can ask the interpreter to return only the one at a specific position. This is done by adding a second pair of square brackets and passing the desired index. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video[cast-members][2]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Second video with a cast-members section",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
This would produce:
After getting a child node by name, if that child node has at least one child node and you know the name of that grand-child, pass that name to the square brackets applied after /. Here is an example: using System;
using System.Xml;
using System.Windows.Forms;
public class Exercise
{
public static int Main()
{
XmlDocument xdVideos = new XmlDocument();
xdVideos.Load("../../Videos.xml");
XmlElement xeVideo = xdVideos.DocumentElement;
XmlNodeList xnlVideos = xeVideo.SelectNodes("/videos/video[categories]/keywords[keyword]");
foreach(XmlNode xnVideo in xnlVideos)
MessageBox.Show(xnVideo.OuterXml,
"Videos with both Format and Category sections",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return 0;
}
}
This would produce:
|
|
|||||||||||||||||
|
|