基于孙子对XML文档进行排序

时间:2015-06-10 10:23:39

标签: c# xml linq sorting

我有以下XML,我希望“action”节点基于属性值“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>

例如,在轮次no = 2中,动作节点不是顺序的,动作7不是第一个孩子,第二个在那里。我希望它是第一个。因此,我的排序文档的轮次no = 2应该如下所示:

<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>

我如何使用LINQ或其他简单的方法来实现。注意在排序后只有动作节点会改变,其他节点将保持在同一个地方。

2 个答案:

答案 0 :(得分:1)

这应该根据需要对xml的action部分进行排序。需要在Select()内删除以取消当前无序操作与父项的关联。完成后,我们重新添加有序操作。

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());
}

答案 1 :(得分:0)

正如您所说,如果操作都在卡片后面进行分组,您不必介意,可以使用LINQ to XML解析它并删除所有操作元素,并按排序顺序添加它们:

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);
}

如果你已经在你的代码中解析了XML,那么你可以在阅读每一轮时简单地对它们进行排序。