Solved

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

Posted on 2014-10-21
9
204 Views
Last Modified: 2014-10-22
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>
0
Comment
Question by:g_johnson
  • 5
  • 4
9 Comments
 
LVL 4

Author Comment

by:g_johnson
ID: 40395473
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,
0
 
LVL 32

Expert Comment

by:it_saige
ID: 40395710
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:Capture.JPG
-saige-
0
 
LVL 4

Author Comment

by:g_johnson
ID: 40397343
I can certainly try this, but I'm wondering why the xPath technique does not work if there is a namespace in the element.
0
 
LVL 32

Expert Comment

by:it_saige
ID: 40397451
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. -Capture.JPGVersus the non-Namespace version, where the Node Name is equal to the XML Element Name; e.g. -Capture.JPG
-saige-
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 4

Author Comment

by:g_johnson
ID: 40397744
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?
0
 
LVL 32

Expert Comment

by:it_saige
ID: 40397918
Remove the brackets from around your namespace definition.

-saige-
0
 
LVL 32

Accepted Solution

by:
it_saige earned 500 total points
ID: 40397950
In other words; this line -
oManager.AddNamespace("ns", "{http://www.junk.com/xml/mp/order/R1.1}");

Open in new window

Should be entered this way -
oManager.AddNamespace("ns", "http://www.junk.com/xml/mp/order/R1.1");

Open in new window


-saige-
0
 
LVL 32

Expert Comment

by:it_saige
ID: 40397966
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 -Capture.JPG
-saige-
0
 
LVL 4

Author Closing Comment

by:g_johnson
ID: 40398029
Thank you.  You've been very helpful!
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

The Problem How to write an Xquery that works like a SQL outer join, providing placeholders for absent data on the outer side?  I give a bit more background at the end. The situation expressed as relational data Let’s work through this.  I’ve …
Introduction Hi all and welcome to my first article on Experts Exchange. A while ago, someone asked me if i could do some tutorials on object oriented programming. I decided to do them on C#. Now you may ask me, why's that? Well, one of the re…
This video discusses moving either the default database or any database to a new volume.
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now