I have an xml file with two lists, forming parent-child relations, like this:
<Categories> <Category id="10000">Category 1</Category> <Category id="10100">Category 2</Category> <Category id="10101">Category 3</Category> ... </Categories>
<Actions> <Action name="Action 1"><Categories><Category id="10100"/><Category id="10102"/></Categories></Action> <Action name="Action 2"><Categories><Category id="10101"/><Category id="10103"/></Categories></Action> ... </Actions>
Each Action has at least one category from master list. I am trying in my query to expand categories in each action with their names from parent category list, so the output structure would be something like this:
class 开发者_StackOverflowAction {
public string ActionName; public List<Category
> Categories; }class Category {
public string CategoryName; public int CategoryId; }
I am completely lost, please help.
You could first create a List to store unique Category objects you then reference when creating Action objects. Example C# code:
XDocument doc = XDocument.Load(@"..\..\XMLFile1.xml");
List<Category> referencedCategories =
(from cat in doc.Root.Element("Categories").Elements("Category")
where doc.Root.Element("Actions").Elements("Action").Elements("Categories").Elements("Category").Any(c2 => cat.Attribute("id").Value == c2.Attribute("id").Value)
select new Category()
{
CategoryId = (int)cat.Attribute("id"),
CategoryName = (string)cat
}).ToList();
List<Action> actions =
(from action in doc.Root.Element("Actions").Elements("Action")
select new Action()
{
ActionName = (string)action.Attribute("name"),
Categories = (from cat in referencedCategories
where action.Element("Categories").Elements("Category").Any(cat2 => (int)cat2.Attribute("id") == cat.CategoryId)
select cat).ToList()
}).ToList();
foreach (Action action in actions)
{
Console.WriteLine("Action {0}:", action.ActionName);
foreach (Category cat in action.Categories)
{
Console.WriteLine("\tId: {0}; Name: {1}", cat.CategoryId, cat.CategoryName);
}
Console.WriteLine();
}
With the XML sample being
<Root>
<Categories>
<Category id="10000">Category 1</Category>
<Category id="10100">Category 2</Category>
<Category id="10101">Category 3</Category>
<Category id="10102">Category 4</Category>
<Category id="10103">Category 5</Category>
</Categories>
<Actions>
<Action name="Action 1">
<Categories>
<Category id="10100"/>
<Category id="10102"/>
</Categories>
</Action>
<Action name="Action 2">
<Categories>
<Category id="10101"/>
<Category id="10103"/>
</Categories>
</Action>
</Actions>
</Root>
that sample outputs
Action Action 1:
Id: 10100; Name: Category 2
Id: 10102; Name: Category 4
Action Action 2:
Id: 10101; Name: Category 3
Id: 10103; Name: Category 5
If you prefer to use the join clause the code could be changed as follows:
XDocument doc = XDocument.Load(@"..\..\XMLFile1.xml");
List<Category> referencedCategories =
(from cat in doc.Root.Element("Categories").Elements("Category")
join cat2 in doc.Root.Element("Actions").Elements("Action").Elements("Categories").Elements("Category") on cat.Attribute("id").Value equals cat2.Attribute("id").Value
select new Category()
{
CategoryId = (int)cat.Attribute("id"),
CategoryName = (string)cat
}).ToList();
List<Action> actions =
(from action in doc.Root.Element("Actions").Elements("Action")
select new Action()
{
ActionName = (string)action.Attribute("name"),
Categories = (from cat in referencedCategories
join cat2 in action.Element("Categories").Elements("Category") on cat.CategoryId equals (int)cat2.Attribute("id")
select cat).ToList()
}).ToList();
精彩评论