XPath and XmlNodeList, the horror, the horror!

  • Thread starter Thread starter DotNetNewbie
  • Start date Start date
D

DotNetNewbie

Thanks all for the previous help btw.

What is going on here? It works yet it doesn't want to work in a
loop.



XmlNodeList nodeList = root.SelectNodes(String.Format("/cars/
mfg[@name='{0}'/model]", folderName));


This works:

nodeList[0].ChildNodes[0].Attributes["name"].Value.ToString()

nodeList[0].ChildNodes[1].Attributes["name"].Value.ToString());


but if I try and loop through them I get an error: Expression must
evaluate to a node-set.

my loop:

for (int x = 0; x < nodeList[0].ChildNodes.Count; x++)
{
XmlNode node = nodeList[0].ChildNodes[x];

url = new UrlPattern();

url.Name = node.Attributes["name"].Value.ToString();
url.RegexString = node.Attributes["regexString"].Value.ToString();
url.RealPath = node.Attributes["realPath"].Value.ToString();
url.Format = node.Attributes["format"].Value.ToString();


rgUrlPatterns.Add(url);
}
 
Well, what does the xpath mean?

XmlNodeList nodeList = root.SelectNodes(String.Format("/cars/
mfg[@name='{0}'/model]", folderName));

Support folderName is "Foo", then this gives xpath of

"/cars/mfg[@name='Foo'/model]"

I suggest that you simply need to lose the single quotes.

Marc
 
When? At compile-time, or execution time?

Where? Which line of code?

Could you post a short but complete program which demonstrates the
problem?

Seehttp://www.pobox.com/~skeet/csharp/complete.htmlfor details of
what I mean by that.


Jon,

My XML:

<?xml version="1.0"?>
<cars>
<car mfg="ford">
<model name="escort" />
<model name="windstar" />
</car>
<car mfg="honda">
<model name="accord" />
<model name="civic" />
<model name="s2000" />
</car>
</cars>


My codebehind:

protected void Page_Load(object sender, EventArgs e)
{


string pathToFile = String.Format("{0}/cars.xml",

HttpContext.Current.Request.PhysicalApplicationPath);


XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(pathToFile);

XmlNode root = xmlDoc.DocumentElement;

string mfgName = "honda";

XmlNodeList nodeList = root.SelectNodes(String.Format("/
cars/car[@mfg='{0}'/model]", mfgName));


//Response.Write("nodeList: " + (null == nodeList));
//Response.Write("nodelist2: " +
nodeList[0].ChildNodes[0].Attributes["name"].Value.ToString());
//Response.Write("nodelist2: " +
nodeList[0].ChildNodes[1].Attributes["name"].Value.ToString());
//Response.End();



for (int x = 0; x < nodeList[0].ChildNodes.Count; x++)
{
XmlNode node = nodeList[0].ChildNodes[x];

Response.Write("forloop name = " +
node.Attributes["name"].Value.ToString());


}

}
 
DotNetNewbie submitted this idea :
Thanks all for the previous help btw.

What is going on here? It works yet it doesn't want to work in a
loop.



XmlNodeList nodeList = root.SelectNodes(String.Format("/cars/
mfg[@name='{0}'/model]", folderName));

Shouldn't that XPath be
"/cars/mfg[@name='{0}']/model"
(moved the ] bracket)
or is that a typo in the post?

Hans Kesting
 
DotNetNewbie said:
<cars>
<car mfg="ford">
<model name="escort" />
<model name="windstar" />
</car>
<car mfg="honda">
<model name="accord" />
<model name="civic" />
<model name="s2000" />
</car>
</cars>


My codebehind:

protected void Page_Load(object sender, EventArgs e)
{


string pathToFile = String.Format("{0}/cars.xml",

HttpContext.Current.Request.PhysicalApplicationPath);


XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(pathToFile);

XmlNode root = xmlDoc.DocumentElement;

string mfgName = "honda";

XmlNodeList nodeList = root.SelectNodes(String.Format("/
cars/car[@mfg='{0}'/model]", mfgName));

Looks to me like you want
XmlNodeList modelList = xmlDoc.SelectNodes(string.Format(
"/cars/car[@mfg = '{0}']/model", mfgName));
and then simply
foreach (XmlElement model in modelList)
{
Response.Write(model.GetAttribute("name") + "<br>");
}
 
Now would be a very good time to learn how to write a short but
complete program, rather than presenting codebehind snippets.

Seehttp://pobox.com/~skeet/csharp/incomplete.html

You'll find it a *lot* quicker to debug problems like this (which have
nothing to do with ASP.NET per se) when you've got them in a small test
harness.

Ok the code works fine in a Console application, but on the web I am
getting an error.

My console code (xml file: http://pastebin.com/m550db746 )


using System;
using System.Xml;

class Program
{
static void Main(string[] args)
{

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(@"E:\Test\cars.xml");
string mfgName = "honda";

XmlNodeList modelList = xmlDoc.SelectNodes(string.Format("/
cars/car[@mfg = '{0}']/model", mfgName));

foreach (XmlElement model in modelList)
{
Console.WriteLine(model.GetAttribute("name"));
}

Console.ReadLine();


}
}

I used the exact same code for my web page, but I replaced the
console.writes with response.writes, and loading the XML by URL.

My code is here:

protected void Page_Load(object sender, EventArgs e)
{
XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(Server.MapPath("/cars.xml"));
string mfgName = "honda";

XmlNodeList modelList = xmlDoc.SelectNodes(string.Format("/
cars/car[@mfg = '{0}']/model", mfgName));

foreach (XmlElement model in modelList)
{
Response.Write("<br>Name: " +
model.GetAttribute("name"));
}
}

(same XML file).

Again the error on the webpage is:

Exception Details: System.Xml.XPath.XPathException: Expression must
evaluate to a node-set.
Source Error:
foreach (XmlElement page in nodeList)
 
Again the error on the webpage is:

Exception Details: System.Xml.XPath.XPathException: Expression must
evaluate to a node-set.
Source Error:
foreach (XmlElement page in nodeList)

Has it definitely load the file correctly? What does it look like in
the debugger?
 
DotNetNewbie said:
I used the exact same code for my web page, but I replaced the
console.writes with response.writes, and loading the XML by URL.

My code is here:

protected void Page_Load(object sender, EventArgs e)
{
XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(Server.MapPath("/cars.xml"));
string mfgName = "honda";

XmlNodeList modelList = xmlDoc.SelectNodes(string.Format("/
cars/car[@mfg = '{0}']/model", mfgName));

foreach (XmlElement model in modelList)
{
Response.Write("<br>Name: " +
model.GetAttribute("name"));
}
}

(same XML file).

Again the error on the webpage is:

Exception Details: System.Xml.XPath.XPathException: Expression must
evaluate to a node-set.
Source Error:
foreach (XmlElement page in nodeList)

But your code above has
foreach (XmlElement model in modelList)
so why would the error message say
foreach (XmlElement page in nodeList)
? That does not make sense to me. It looks like the error is elsewhere,
not in the code you provided.
 
Has it definitely load the file correctly? What does it look like in
the debugger?

yes the file is loaded correctly, I put debug tag when it loads the
file, and during the loop.

After it loads the file and hits the forloop, in vs.net I can view
that the cars.xml file has loaded just fine.
 
yes the file is loaded correctly, I put debug tag when it loads the
file, and during the loop.

After it loads the file and hits the forloop, in vs.net I can view
that the cars.xml file has loaded just fine.

Ok got it to work, I was referencing the child nodes incorrectly!
thanks for all your replies!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top