Linq to XML simple get attribute from node statement
Here's 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 here's 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 ke开发者_运维知识库ep getting an "object not set to an instance of an object" exception.
What I'm trying to return is the type of the selected node based on the type of a parent node, i.e., if the theme is "Agile" and the parent node is "Project" then the return value should be "Iteration". That's the final outcome but I never got that far because I got stuck with what you see above.
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();
}
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.
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()
.
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);
精彩评论