Reputation: 417
I have following XML and I want the "action" node to be in sorted order based on attribute value "no".
<game gamecode="10065904">
<general>
<startdate>2015-06-10 07:59:04</startdate>
<players>
<player seat="1" name="player1" chips="2,937" dealer="1" win="0" bet="20" rebuy="0" addon="0" reg_code="-" />
<player seat="3" name="ponda22c" chips="780" dealer="0" win="0" bet="0" rebuy="0" addon="0" reg_code="-" />
<player seat="5" name="Mesut1Rebel" chips="0" dealer="0" win="0" bet="0" rebuy="0" addon="0" reg_code="-" />
<player seat="6" name="player4" chips="10,746" dealer="0" win="0" bet="420" rebuy="0" addon="0" reg_code="-" />
<player seat="8" name="player5" chips="3,670" dealer="0" win="0" bet="420" rebuy="0" addon="0" reg_code="-" />
<player seat="10" name="player6" chips="5,143" dealer="0" win="2,558" bet="1,700" rebuy="0" addon="0" reg_code="-" />
</players>
</general>
<round no="0">
<action no="1" player="player4" type="1" sum="10" cards="[cards]" />
<action no="2" player="player5" type="2" sum="20" cards="[cards]" />
</round>
<round no="1">
<cards type="Pocket" player="player1">X X</cards>
<action no="4" player="player1" type="3" sum="20" cards="" />
<cards type="Pocket" player="player4">X X</cards>
<action no="5" player="player4" type="3" sum="10" cards="" />
<cards type="Pocket" player="player5">X X</cards>
<action no="6" player="player5" type="4" sum="0" cards="" />
<cards type="Pocket" player="player6">X X</cards>
<action no="3" player="player6" type="3" sum="20" cards="" />
</round>
<round no="2">
<cards type="Flop" player="">H4 CQ C8</cards>
<action no="10" player="player1" type="0" sum="0" cards="" />
<action no="7" player="player4" type="4" sum="0" cards="" />
<action no="11" player="player4" type="3" sum="80" cards="" />
<action no="8" player="player5" type="4" sum="0" cards="" />
<action no="12" player="player5" type="3" sum="80" cards="" />
<action no="9" player="player6" type="5" sum="80" cards="" />
</round>
<round no="3">
<cards type="Turn" player="">H9</cards>
<action no="13" player="player4" type="4" sum="0" cards="" />
<action no="16" player="player4" type="3" sum="320" cards="" />
<action no="14" player="player5" type="4" sum="0" cards="" />
<action no="17" player="player5" type="3" sum="320" cards="" />
<action no="15" player="player6" type="5" sum="320" cards="" />
</round>
<round no="4">
<cards type="River" player="">HJ</cards>
<action no="18" player="player4" type="4" sum="0" cards="" />
<action no="21" player="player4" type="0" sum="0" cards="" />
<action no="19" player="player5" type="4" sum="0" cards="" />
<action no="22" player="player5" type="0" sum="0" cards="" />
<action no="20" player="player6" type="5" sum="1,280" cards="" />
</round>
</game>
For example in round no=2, action nodes are not in sequence, action no 7 is not the first child, its second over there. I want it to be first. So my sorted document's round no=2 should look as follows:
<round no="2">
<cards type="Flop" player="">H4 CQ C8</cards>
<action no="7" player="player4" type="4" sum="0" cards="" />
<action no="8" player="player5" type="4" sum="0" cards="" />
<action no="9" player="player6" type="5" sum="80" cards="" />
<action no="10" player="player1" type="0" sum="0" cards="" />
<action no="11" player="player4" type="3" sum="80" cards="" />
<action no="12" player="player5" type="3" sum="80" cards="" />
</round>
How can I do that using LINQ or by some other easy way. Note after the sorting only action nodes will change, other nodes will remain at same place.
Upvotes: 0
Views: 109
Reputation: 2716
This should sort the action section of the xml as you want. The remove within the Select()
is needed to disassociate the current unordered actions from the parent. Once that is done we add the ordered action back in.
static void Main()
{
var root = XElement.Parse(xmlToParse);
var orderedRoundElements= root.Elements("round")
.Select(element=>{
var actions = element.Elements("action")
.OrderBy(elem=> (int)elem.Attribute("no"))
.ToList();
actions.Remove();
element.Add(actions);
return element;
}).ToList();
Console.WriteLine(root.ToString());
}
Upvotes: 1
Reputation: 26213
As you say you don't mind if the actions are all grouped after the cards, you can parse this using LINQ to XML and remove all action elements and add them at the end in sorted order:
var doc = XDocument.Parse(xml);
foreach (var round in doc.Descendants("round"))
{
var sortedActions = round.Elements("action")
.OrderBy(e => (int)e.Attribute("no"))
.ToList();
sortedActions.Remove();
round.Add(sortedActions);
}
If you're already parsing the XML in your code as you imply, you may be able to simply sort these while reading each round.
Upvotes: 0