tags:

views:

58

answers:

4

Ok so heres the code snippet.

            XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
            string result = "";
            var childType = from t in themes.Descendants()
                            where t.Attribute("name").Value.Equals(theme)
                            select new { value = t.Attribute("type").Value };

            foreach (var t in childType) {
                result += t.value;
            }
            return result;

and heres the xml

<?xml version="1.0" encoding="utf-8" ?>
<themes>
  <theme name="Agile">
    <root type="Project">
      <node type="Iteration" >
        <node type="Story">
          <node type="Task"/>
        </node>
      </node>
    </root>
  </theme>
  <theme name="Release" >
    <root type="Project">
      <node type="Release">
        <node type="Task" />
        <node type="Defect" />
      </node>
    </root>
  </theme>
</themes>

what am I doing wrong? I keep getting an object not set to an instance of an object exception.

----edit-----

ok let me add abit more, what I'm trying to return is the type of the selected node based on the type of a parent node, IE, if the theme is "Agile" and the parent node is "Project" then the return value should be "Iteration". Thats the final outcome but I never got that far because I got stuck with what you see above.

A: 

I'm not cleared about your question. Here is my solution( as i understood)

var childType = themes.Descendants("theme")
                             .Where(X => X.Attribute("name").Value == "Agile")
                             .Where(X => X.Descendants("root").Attributes("type").First().Value == "Project")
                             .Select(X => X.Descendants("node").Attributes("type").First().Value);
Pramodh
A: 

There are two errors in your query.

First one is:

from t in themes.Descendants()

This will give you all themes elements.
If you want the theme elements, you must specify it, by filtering like:

from t in themes.Descendants("theme")

The second error will consequently be

select new { value = t.Attribute("type").Value }

because t will be a theme element, with no attribute "type".
I can't help on this one because it is not clear what the final result must be.

Edit: According to the added informations, this should do the trick:

        var childType =
            from t in doc.Descendants("theme")
            where t.Attribute("name").Value.Equals(theme)
            select t.Element("root")
                    .Element("node")
                    .Attribute("type").Value;

However, this is meant to retrieve multiple types from nodes with the same theme name.
If the type will always be the same, you should consider calling .SingleOrDefault() .

Alex Bagnolini
edited to provide more info
Morgeh
A: 

I think you want something closer to this:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var childType = from t in themes.Descendants("theme")
                where t.Attribute("name").Value.Equals(theme)
                select new { value = t.Descendants().Attribute("type").Value };

foreach (var t in childType) {
    result += t.value;
}
return result;

EDIT: Based on your additional info, perhaps this is even closer:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var childType = from t in themes.Descendants("theme")
                where t.Attribute("name").Value.Equals(theme)
                where t.Element("node").Attribute("type").Value == parent
                select new { value = t.Descendants().Attribute("type").Value };

foreach (var t in childType) {
    result += t.value;
}
return result;

EDIT 2: This is working for me:

XDocument themes = XDocument.Load(HttpContext.Current.Server.MapPath("~/Models/Themes.xml"));
string result = "";
var theme = "Agile";
var parent = "Project";
var childType = from t in themes.Descendants("theme")
            where t.Attribute("name").Value.Equals(theme)
            where t.Element("root").Attribute("type").Value == parent
            from children in t.Element("root").Descendants()
            select new { value = children.Attribute("type").Value };
foreach (var t in childType) {
    result += t.value;
}
return result;

EDIT 3: Here's the complete working program, just throw it in a class in a console application.

static void Main(string[] args)
        {
            var xml = "<themes><theme name='Agile'><root type='Project'><node type='Iteration' ><node type='Story'><node type='Task'/></node></node></root></theme><theme name='Release' ><root type='Project'><node type='Release'><node type='Task' /><node type='Defect' /></node></root></theme></themes>";
            XDocument themes = XDocument.Parse(xml);
            string result = "";
            var theme = "Agile";
            var parent = "Project";
            var childType = from t in themes.Descendants("theme")
                            where t.Attribute("name").Value.Equals(theme)
                            where t.Element("root").Attribute("type").Value == parent
                            from children in t.Element("root").Descendants()
                            select new { value = children.Attribute("type").Value };

            foreach (var t in childType)
            {
                Console.WriteLine(t.value);
            }

            Console.Read();

        }
Chris Conway
there isn't a method version of FirstNode its a property that doesn't have an attribute method.
Morgeh
good catch, updated the code.
Chris Conway
I had to add .First() to t.Descendants() within the select statement to get it to compile, however I'm still getting object not set to an instance of an object exceptions
Morgeh
Try my second edit to see if it is what you want.
Chris Conway
your 2nd edit is returning blank values for me. I couldn't be to do with the layout of my xml could it?
Morgeh
I've updated again showing the complete working example based on what you've given. If it's still not working, take a look at your xml and make sure it's the same format as what I have. It should be working for you unless there's something else in the xml.
Chris Conway
A: 

Ok here's what I did in the end, it's not very pretty but it works. Its based on the answer by Pramodh with a few tweeks.

string result = "";
                var childType = themes.Descendants("theme")
                                               .Where(x => x.Attribute("name").Value == theme)
                                               .Where(x => x.Descendants("node").First().Attribute("type").Value == parentType)
                                               .Select(x => x.Descendants("node").First().Descendants().First().Attribute("type").Value);

                foreach (var t in childType) {
                    result += t;
                }
                return result;

now if I pass in theme "Agile" and parent "Iteration" it returns story.

Like I said not very pretty but it works.

Thank you to everyone who posted answers.

Morgeh