By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,458 Members | 1,299 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,458 IT Pros & Developers. It's quick & easy.

Selecting XML nodes w/ namespace and XElement

P: n/a
I'm playing around with XElement stuff, and I've come across a difficulty.
The XML document that I'm reading contains an xmlns declaration on the main
node...

<root xmlns="http://www.me.com">
<ANode>
<BNode>Hello</BNode>
<BNode>Goodbye</BNode>
</ANode>
</root>

I want to be able to query this document using XPath. I can successfully
do this with the following:

XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = doc.SelectNodes("/t:root/t:ANode/t:BNode", nsm).Count;

.... and I see that n = 2.

But when I try to convert this to XElement (and who knows I may be
WWWAAAYYY off here as I'm just starting to look at this):

XmlReader rdr = XmlReader.Create(new StringReader(s));
XElement x = XElement.Load(rdr);
XmlNamespaceManager nsm = new XmlNamespaceManager(rdr.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = x.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm).Count();

.... I get n = 0.
What am I doing wrong?

-mdb

Jul 9 '08 #1
Share this Question
Share on Google+
11 Replies


P: n/a
"Michael Bray" <mb***@dontemailme.comwrote in message
news:Xn*****************@207.46.248.16...
I'm playing around with XElement stuff, and I've come across a difficulty.
The XML document that I'm reading contains an xmlns declaration on the
main
node...

<root xmlns="http://www.me.com">
<ANode>
<BNode>Hello</BNode>
<BNode>Goodbye</BNode>
</ANode>
</root>

I want to be able to query this document using XPath. I can successfully
do this with the following:

XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = doc.SelectNodes("/t:root/t:ANode/t:BNode", nsm).Count;

... and I see that n = 2.

But when I try to convert this to XElement (and who knows I may be
WWWAAAYYY off here as I'm just starting to look at this):

XmlReader rdr = XmlReader.Create(new StringReader(s));
XElement x = XElement.Load(rdr);
XmlNamespaceManager nsm = new XmlNamespaceManager(rdr.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = x.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm).Count();

... I get n = 0.
What am I doing wrong?
I've not done much with this new XElement either but I'd be willing to guess
that since x is root and in this case is the top most node (in the
XmlDocument the document is the top most node and root is a child). then
the path is wrong. / refers to root and root doesn't have a child called
root.

Try:-

"t:ANode/t:BNode"

I'm currently on a my 2000 machine so I can't test that at the moment.

--
Anthony Jones - MVP ASP/ASP.NET
Jul 9 '08 #2

P: n/a
Dude,

First, understand the difference between XMLDocument and XMLReader.
XMLDocument is inmemory .. where are XMLReader is not a cache.

thus, when you first queried you got the count, where are when you did the
second mechanism, it doesn't have loaded the entire XML into memory.

Hope am clear to you,


"Michael Bray" <mb***@dontemailme.comwrote in message
news:Xn*****************@207.46.248.16...
I'm playing around with XElement stuff, and I've come across a difficulty.
The XML document that I'm reading contains an xmlns declaration on the
main
node...

<root xmlns="http://www.me.com">
<ANode>
<BNode>Hello</BNode>
<BNode>Goodbye</BNode>
</ANode>
</root>

I want to be able to query this document using XPath. I can successfully
do this with the following:

XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = doc.SelectNodes("/t:root/t:ANode/t:BNode", nsm).Count;

... and I see that n = 2.

But when I try to convert this to XElement (and who knows I may be
WWWAAAYYY off here as I'm just starting to look at this):

XmlReader rdr = XmlReader.Create(new StringReader(s));
XElement x = XElement.Load(rdr);
XmlNamespaceManager nsm = new XmlNamespaceManager(rdr.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = x.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm).Count();

... I get n = 0.
What am I doing wrong?

-mdb
Jul 10 '08 #3

P: n/a
On Jul 10, 12:24*pm, "Chakravarthy" <dskch...@msn.comwrote:
First, understand the difference between XMLDocument and XMLReader.
XMLDocument is inmemory .. where are XMLReader is not a cache.

thus, when you first queried you got the count, where are when you did the
second mechanism, it doesn't have loaded the entire XML into memory.
Doesn't XElement.Load(rdr) load the whole thing into memory though?
That's certainly what I'd expect.

Jon
Jul 10 '08 #4

P: n/a
On Jul 10, 12:45*am, "Anthony Jones" <A...@yadayadayada.comwrote:
"Michael Bray" <mb...@dontemailme.comwrote in message

news:Xn*****************@207.46.248.16...


I'm playing around with XElement stuff, and I've come across a difficulty.
The XML document that I'm reading contains an xmlns declaration on the
main
node...
<root xmlns="http://www.me.com">
* *<ANode>
* * * <BNode>Hello</BNode>
* * * <BNode>Goodbye</BNode>
* *</ANode>
</root>
I want to be able to query this document using XPath. *I can successfully
do this with the following:
XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
XmlNamespaceManager nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = doc.SelectNodes("/t:root/t:ANode/t:BNode", nsm).Count;
... *and I see that n = 2.
But when I try to convert this to XElement (and who knows I may be
WWWAAAYYY off here as I'm just starting to look at this):
XmlReader rdr = XmlReader.Create(new StringReader(s));
XElement x = XElement.Load(rdr);
XmlNamespaceManager nsm = new XmlNamespaceManager(rdr.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
int n = x.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm).Count();
... *I get n = 0.
What am I doing wrong?

I've not done much with this new XElement either but I'd be willing to guess
that since x is root and in this case is the top most node (in the
XmlDocument the document is the top most node and root is a child). *then
the path is wrong. */ refers to root and root doesn't have a child called
root.

*Try:-

"t:ANode/t:BNode"
Yes, this is correct - "/" refers to the root node in the XML tree,
which is document in XmlDocument, but <rootelement in this case.
You may either follow the suggestion above, or load the XML into
System.Xml.Linq.XDocument instead - then you'll get the usual
behavior.

By the way, why XPath? The whole point of the new APIs is to use LINQ
queries instead:

XNamespace t = "http://www.me.com";
var result = doc.Elements(t + "ANode").Elements(t + "BNode");
Jul 10 '08 #5

P: n/a
Pavel Minaev <in****@gmail.comwrote in news:ec4a9b96-77b8-4035-bbe3-
ac**********@k13g2000hse.googlegroups.com:
Yes, this is correct - "/" refers to the root node in the XML tree,
which is document in XmlDocument, but <rootelement in this case.
You may either follow the suggestion above, or load the XML into
System.Xml.Linq.XDocument instead - then you'll get the usual
behavior.

By the way, why XPath? The whole point of the new APIs is to use LINQ
queries instead:

XNamespace t = "http://www.me.com";
var result = doc.Elements(t + "ANode").Elements(t + "BNode");
I'm using XPath because I want to be able to specify in a configuration
file which set of nodes to analyze. What you say makes a lot of sense if I
always know the path and can hard code it.

Even so, testing your code yields no results:

string s = "<root xmlns='http://www.me.com'><ANode><BNode>Hello</BNode>
<BNode>Goodbye</BNode></ANode></root>";

XDocument doc = XDocument.Parse(s);
XNamespace ns = "http://www.me.com";
int nn = doc.Elements(ns + "ANode").Elements(ns + "BNode").Count();

yields.. nn = 0. did I miss something?

-mdb
Jul 10 '08 #6

P: n/a
"Anthony Jones" <An*@yadayadayada.comwrote in
news:##**************@TK2MSFTNGP05.phx.gbl:
I've not done much with this new XElement either but I'd be willing to
guess that since x is root and in this case is the top most node (in
the XmlDocument the document is the top most node and root is a
child). then the path is wrong. / refers to root and root doesn't
have a child called root.

Try:-

"t:ANode/t:BNode"
Yup tried that before I posted (along with every other path I could think
of).. Same result - 0 nodes selected.

I'm just grasping at straws at this point - almost ready to abandon XML
Linq for now and stick with what works.

-mdb
Jul 10 '08 #7

P: n/a
Michael Bray wrote:
Even so, testing your code yields no results:

string s = "<root xmlns='http://www.me.com'><ANode><BNode>Hello</BNode>
<BNode>Goodbye</BNode></ANode></root>";

XDocument doc = XDocument.Parse(s);
XNamespace ns = "http://www.me.com";
int nn = doc.Elements(ns + "ANode").Elements(ns + "BNode").Count();

yields.. nn = 0. did I miss something?
Yes, certainly, the XDocument doc you construct has a root element named
'root' that your code ignores. You need/want
doc.Root.Elements(ns + "ANode").Elements(ns + "BNode").Count()
or (naming the root explicitly)
doc.Element(ns + "root").Elements(ns + "ANode").Elements(ns +
"BNode").Count()

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
Jul 10 '08 #8

P: n/a
Michael Bray wrote:
"Anthony Jones" <An*@yadayadayada.comwrote in
news:##**************@TK2MSFTNGP05.phx.gbl:
>I've not done much with this new XElement either but I'd be willing to
guess that since x is root and in this case is the top most node (in
the XmlDocument the document is the top most node and root is a
child). then the path is wrong. / refers to root and root doesn't
have a child called root.

Try:-

"t:ANode/t:BNode"

Yup tried that before I posted (along with every other path I could think
of).. Same result - 0 nodes selected.
Here is a working sample that outputs 2:

XElement root = XElement.Load(@"..\..\XMLFile1.xml");
XmlNamespaceManager mgr = new XmlNamespaceManager(new
NameTable());
mgr.AddNamespace("pf", "http://www.me.com");

Console.WriteLine(root.XPathSelectElements("pf:ANo de/pf:BNode",
mgr).Count());

XML document is

<?xml version="1.0" encoding="utf-8" ?>
<root xmlns="http://www.me.com">
<ANode>
<BNode>Hello</BNode>
<BNode>Goodbye</BNode>
</ANode>
</root>

If your code does not find anything then please show us a complete
sample that demonstrates that, somewhere there must be a mistake.

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
Jul 10 '08 #9

P: n/a
"Anthony Jones" <An*@yadayadayada.comwrote in
news:##**************@TK2MSFTNGP05.phx.gbl:
I've not done much with this new XElement either but I'd be willing to
guess that since x is root and in this case is the top most node (in
the XmlDocument the document is the top most node and root is a
child). then the path is wrong. / refers to root and root doesn't
have a child called root.

Try:-

"t:ANode/t:BNode"

OK hmmm.. as I was playing around I think I fixed it... I can query
using both the XPath query mode and the Elements(..)... Here's the code
that works for me:

string s = "<root xmlns='http://www.me.com'><ANode><BNode>Hello</BNode>
<BNode>Goodbye</BNode></ANode></root>";

XmlReader rdr = XmlReader.Create(new StringReader(s));
XDocument doc = XDocument.Load(rdr);
XmlNamespaceManager nsm = new XmlNamespaceManager(rdr.NameTable);
nsm.AddNamespace("t", "http://www.me.com");
XNamespace ns = "http://www.me.com";

int n = doc.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm).Count();
int nn = doc.Elements(ns + "root").Elements(ns + "ANode").Elements(ns +
"BNode").Count();
int nnn = doc.Elements("root").Elements("ANode").Elements("B Node").Count();

var q = doc.XPathSelectElements("/t:root/t:ANode/t:BNode", nsm);
foreach (var v in q) Console.WriteLine(v.Value);
yields.... n = 2 nn = 2 nnn = 0
and outputs: Hello Goodbye

so I think the main thing that fixed it was loading into XDocument instead
of XElement. Also, when querying using the Elements() I needed to make
sure I added the XNamespace.

Thanks to everyone for their input... I knew it would be something simple
I was missing.

-mdb

Jul 10 '08 #10

P: n/a
Martin Honnen <ma*******@yahoo.dewrote in news:#3LFOoq4IHA.4340
@TK2MSFTNGP06.phx.gbl:
Yes, certainly, the XDocument doc you construct has a root element named
'root' that your code ignores. You need/want
doc.Root.Elements(ns + "ANode").Elements(ns + "BNode").Count()
or (naming the root explicitly)
doc.Element(ns + "root").Elements(ns + "ANode").Elements(ns +
"BNode").Count()
Haha yeah I actually just meandered into the same solution and posted the
same answer... Turned out that my original problem was that I was loading
into XElement instead of XDocument!

Thanks for you help!!

-mdb
Jul 10 '08 #11

P: n/a
Martin Honnen <ma*******@yahoo.dewrote in news:uTBS$pq4IHA.4340
@TK2MSFTNGP06.phx.gbl:
If your code does not find anything then please show us a complete
sample that demonstrates that, somewhere there must be a mistake.
Hmmm now that is odd... I confirm that this works, but I can't see any
significant difference from what (I thought) I tested... maybe I just
was too blinded by frustration and was making silly mistakes.

Oh well... I have things working like I need them now, so I'm happy again.
Thanks!

-mdb
Jul 10 '08 #12

This discussion thread is closed

Replies have been disabled for this discussion.