Link to home
Start Free TrialLog in
Avatar of g_johnson
g_johnsonFlag for United States of America

asked on

What is wrong with my attempt to read an xml file using xPath expressions (C#)

I am trying to use this code to get to the Order elements in an xml file:

                    IEnumerable<XElement> nodeList = xDoc.XPathSelectElements("//Orders/Order");

I have used this technique before but can't find what I'm doing wrong on this particular one:

The xml file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Orders xmlns="http://www.junk.com/xml/mp/order/R1.1" xmlns:xsi="http://junk/2001/XMLSchema-instance" xsi:schemaLocation="http://www.junk.com/xml/mp/order/R1.1 http://support.junk.com/mp/R1.1/order/Orders.xsd">
    <Order>
        <OrderID>100000009</OrderID>
            (and all sorts of child elements)
    </Order>
    <Order>
        <OrderID>1000000111</OrderID>
            (and all sorts of child elements)
    </Order>
</Orders>
Avatar of g_johnson
g_johnson
Flag of United States of America image

ASKER

I found that this technique works if I strip out everything and the element looks like this:
<Orders>

I then can read it like this:  xDoc.XPathSelectElements("/Order");

However, in reality I can't strip that out.

How do I get around this?

Thanks,
Avatar of it_saige
Try this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

static class XmlExample
{
	public static void Main()
	{
		XmlReader reader = XmlReader.Create("Orders.xml");
		XElement data = XElement.Load(reader);
		XmlNameTable table = reader.NameTable;
		XmlNamespaceManager manager = new XmlNamespaceManager(table);
		manager.AddNamespace("ns", "http://www.junk.com/xml/mp/order/R1.1");
		foreach (XElement order in data.XPathSelectElements("./ns:Order", manager))
		{
			foreach (var pair in (from id in order.Elements() where id.Name.LocalName.Contains("OrderID") select new { id.Name.LocalName, id.Value }))
				Console.WriteLine(string.Format("Name - {0}; Value - {1}", pair.LocalName, pair.Value));
		}
		Console.ReadLine();
	}
}

Open in new window

Orders.xml:
<?xml version="1.0" encoding="UTF-8"?>
<Orders xmlns="http://www.junk.com/xml/mp/order/R1.1" xmlns:xsi="http://junk/2001/XMLSchema-instance" xsi:schemaLocation="http://www.junk.com/xml/mp/order/R1.1 http://support.junk.com/mp/R1.1/order/Orders.xsd">
	<Order>
		<OrderID>100000009</OrderID>
	</Order>
	<Order>
		<OrderID>1000000111</OrderID>
	</Order>
</Orders>

Open in new window

Produces the following output:User generated image
-saige-
I can certainly try this, but I'm wondering why the xPath technique does not work if there is a namespace in the element.
If you compare the Node Name between the Namespace version and non-Namespace version, you will find that when you declare a namespace that the Node Name is equal to the {Namespace} + XML Element Name; e.g. -User generated imageVersus the non-Namespace version, where the Node Name is equal to the XML Element Name; e.g. -User generated image
-saige-
Thanks.  I understand that now, I think.

I combined that info with some other stuff I found in my research, and now this code runs without error but doesn't identify the nodes:

                    XDocument xDoc = XDocument.Load(XMLFileName);

                    XmlNamespaceManager oManager = new XmlNamespaceManager(new NameTable());
                    oManager.AddNamespace("ns", "{http://www.junk.com/xml/mp/order/R1.1}");
                    IEnumerable<XElement> nodeList = xDoc.XPathSelectElements("/ns:Orders/ns:Order",oManager);

Does this have anything to do with it having multiple namespaces in the Orders element?  Or is there something else I'm doing wrong?
Remove the brackets from around your namespace definition.

-saige-
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Making your modifications to the above code -
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

static class XmlExample
{
	public static void Main()
	{
		XDocument document = XDocument.Load("Orders.xml");
		XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
		manager.AddNamespace("ns", "http://www.junk.com/xml/mp/order/R1.1");

		foreach (XElement order in document.XPathSelectElements("/ns:Orders/ns:Order", manager))
		{
			foreach (var pair in (from id in order.Elements() where id.Name.LocalName.Contains("OrderID") select new { id.Name.LocalName, id.Value }))
				Console.WriteLine(string.Format("Name - {0}; Value - {1}", pair.LocalName, pair.Value));
		} 
		Console.ReadLine();
	}
}

Open in new window

Produces the following output -User generated image
-saige-
Thank you.  You've been very helpful!