I have xml file
<root>
<child_1>
<sub_child attr1="text" attr2="text" />
<sub_child attr1="text" attr2="text" />
<sub_child attr1="text" attr2="text" />
</child_1>
<child_2>
<sub_child attr1="text" attr2="text" />
<sub_child attr1="text" attr2="text" />
<sub_child attr1="text" attr2="text" />
</child_2>
<child_3>
<sub_child_1 attr1="text" attr2="text" />
<sub_child_2 attr1="text" attr2="text" />
</child_3>
...
and I want to read sub_child attributes to classes
class SubChild开发者_StackOverflow {
string a1;
string a2;
}
I need two lists of SubChild objects for child_1 and child_2 and two SubChild objects for sub_child_1 and sub_child_2
Now I use linq to xml and my code is
// List<SubChild>
var child_1 = from s in doc.Descendants("sub_child").Where(x => x.Parent.Name == "child_1")
select new SubChild {
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
};
// List<SubChild>
var child_2 = from s in doc.Descendants("sub_child").Where(x => x.Parent.Name == "child_2")
select new SubChild {
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
};
// SubChild
var sub_1 = (from s in doc.Descendants("sub_child_1")
select new SubChild {
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
}).First();
// SubChild
var sub_2 = (from s in doc.Descendants("sub_child_2")
select new SubChild {
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
}).First();
but it looks ugly and I would like to ask is there more clear way to do this?
You can specify a "Path" using .Element()
and .Elements()
, eliminating the where
lambdas.
// untested
var child_1 = from s in doc.Root.Element("child_1").Elements("sub_child")
select new SubChild {
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
};
To go a couple of steps further, you could create a dictionary containing all the subchildren of your elements. This will allow you direct access to the SubChild
's of each element by name.
Dictionary<string, List<SubChild>> dict = doc.Root.Elements().ToDictionary(
e => e.Name.ToString(),
e => e.Elements("sub_child")
.Select(s => new SubChild
{
a1 = s.Attribute("attr1").Value,
a2 = s.Attribute("attr2").Value,
}).ToList());
dict["child_1"][0] // get the first subchild of "child_1"
Do you really have to use linq to xml?
public IEnumerable<SubChild> GetSubChilds(XmlDocument xd)
{
foreach (XmlNode subChild in xd.SelectNodes("/root/*/*"))
{
if (subChild.Name.StartsWith("sub_child"))
{
XmlAttributeCollection atts = subChild.Attributes;
yield return new SubChild { a1 = atts["attr1"].Value, a2 = atts["attr2"].Value };
}
}
}
精彩评论