1

ich have a xml file with the following structure:

<layer1 name="this is layer1">
  <messages>
    <message name ="com_request">0</message>
    <message name="send">1</message>
    <message name="request">2</message>
  </messages>
</layer1>

I try to collect all the message names in one indexer using the code:

SampleCollection<string> paramCollection = new SampleCollection<string>();

string pathxml = @"C:\myXML.xml";
int j=0;

XmlTextReader xmlin = new XmlTextReader(pathxml);
XmlDocument xmldoc = new XmlDocument();
XmlNode node = xmldoc.ReadNode(xmlin);

foreach (XmlNode item in node.ChildNodes)
{
   paramCollection[j] = item.Attributes["message name"].Value;
   Console.WriteLine(paramCollection[j]);
   j++;
}

However it doesn't work. Please help.

1
  • 1
    Can you be more specific with the error? Commented Feb 28, 2011 at 14:21

7 Answers 7

3

The name of your attribute is name, not message name (message is the name of the node).

If you can describe more clearly what you're trying to do, I (or someone else) can provide a more specific solution.

Sign up to request clarification or add additional context in comments.

Comments

1

In addition to what others have mentioned (attribute name is wrong), also your node points to layers1, who only has the direct child messages, so there are no message nodes in your child collection. The same thing in LINQ is trivial - switch if you can:

XDocument doc = XDocument.Load(@"test.xml");
foreach (var item in doc.Descendants("message"))
{
    Console.WriteLine(item.Attribute("name").Value);
}

2 Comments

although i add using system.xml.linq.xdocument, the xdocument is underlined with red squiggle.
@JohnMunich: you should only need using System.Xml.Linq; for this to work
1

The attribute name is not message name, it is name

foreach (XmlNode item in node.ChildNodes)
{
   paramCollection[j] = item.Attributes["name"].Value;
   Console.WriteLine(paramCollection[j]);
   j++;
}

Comments

1

Try this:

XmlDocument xmldoc = new XmlDocument();

XmlNodeList list = xmldoc.SelectNodes("/layer1/messages/message");
List<string> messageNames = new List<string>();

foreach (XmlNode node in list)
{
   messageNames.Add(node.Attributes["name"].Value);    
}

This should extract all <message> nodes using XPath, and then grab their @name attribute into a list of strings.

1 Comment

could you give me any example about xpath?
1

Your node selection is wrong. Its needs to be more like:

string pathxml = @"C:\myXML.xml";
int j=0;

XmlTextReader xmlin = new XmlTextReader(pathxml);
XmlDocument xmldoc = new XmlDocument();
XmlNode node = xmldoc.ReadNode(xmlin);

foreach (XmlNode item in xmldoc.SelectNodes("layer1/messages/message"))
{
    paramCollection[j] = item.Attributes["name"].Value;
    Console.WriteLine(paramCollection[j]);
    j++;
}

So you get a collection of message nodes for the foreach to iterate over. Then the attribute is simple referenced as 'name'

3 Comments

its strange, it still doesn't work. Because of the comments:<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
Can I see an example of the whole file please?
I have just spotted an issue with my code adjustment. Change xmldoc.SelectNodes("layer1/messages/message") to node.SelectNodes("messages/message")
0

If you are using Linq to XML

var doc = XDocument.Load(@"d:\temp\myXml.xml");
var msgnames = from q in doc.Descendants("message")
               select q.Attribute("name").Value; 

foreach(string item in msgnames)
{
    Console.WriteLine(item);
}

Comments

0

Firstly, as other have pointed out, your attribute is called name.

As for your task to collect some values in XML tree, you could have used XPath language to query the document. This would enable you to avoid writing boilerplate code that traverses the tree, as well as easily adapt to XML structure changes:

var doc = new XmlDocument ();
doc.LoadXml (xs);

var attrs = doc.SelectNodes ("/layer1/messages/message/@name");
var values = attrs.Cast<XmlAttribute> ()
    .Select (a => a.Value);

However, since I already used LINQ to cast nodes into attribute instances, it makes sense to use LINQ to XML instead, which was designed for querying XML from C# code:

var doc = XDocument.Parse (xs);
var values = from msg in doc.Descendants ("message")
             select msg.Attribute ("name").Value;

Console.WriteLine (values);

Both of these options are good and depend on what framework you plan to use for working with XML, System.Xml or LINQ to XML. For new code, I suggest using LINQ.

In both cases, you need a simple foreach loop to enumerate values:

foreach (string value in values)
    Console.WriteLine (value);

2 Comments

how to retrieve the value in the values?
Sorry, I don't understand what you mean. values in both cases is of type IEnumerable<string>, meaning you can go through them in a foreach loop: foreach (string value in values). If you need a List<string> or string [] array, call ToList or ToArray on values.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.