XML元素规范化

时间:2013-12-18 00:04:43

标签: c# xml

我有一些XML代表例如4组(A,B,C,D)成员之间的排列。假设A = {A1,A2},B = {B1},C = {C1,C2}和D = {D1,D2,D3}但是当前的XML不正常,因为这些成员在每个成员中以非常规方式组合回答。 “set”属性显示set的名称,“member”显示每个set的每个成员。这个XML喜欢以下内容:

<root>
    <phrase permutation=ABCD>
       <ans number=1>
           <word set=A member=A1/>
           <word set=A member=A2/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=D member=D2/>
       </ans>
       <ans number=2>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=C member=C2/>
           <word set=C member=C3/>
           <word set=D member=D1/>
           <word set=D member=D3/>
       </ans>
    </phrase>
</root>

我想把每个排列放在一个特定的答案中。每个答案应该从A和End的一个成员开始,其中一个成员为D,并且在它们之间仅使用集合B和C中的一个成员。 例如答案A1A2B1C1D2应该与A1B1C1D2,A2B1C1D2分开,答案A1B1C1C2C3D1D3应该分别对A1B1C1D1,A1B1C1D3,A1B1C2D1,A1B1C2D3,A1B1C3D1和A1B1C3D3等最终XML喜欢如XML所示:

<root>
    <phrase permutation=ABCD>
       <ans number=1>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=D member=D2/>
       </ans>
       <ans number=2>
           <word set=A member=A2/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=D member=D2/>
       </ans>
       <ans number=3>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=D member=D1/>
           </ans>
       <ans number=4>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C1/>
           <word set=D member=D3/>
           </ans>
       <ans number=5>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C2/>
           <word set=D member=D1/>
       </ans>
       <ans number=6>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C2/>
           <word set=D member=D3/>
       </ans>
       <ans number=7>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C3/>
           <word set=D member=D1/>
      </ans>
      <ans number=8>
           <word set=A member=A1/>
           <word set=B member=B1/>
           <word set=C member=C3/>
           <word set=D member=D3/>
       </ans>
    </phrase>
</root>

我希望我的问题清楚,你可以帮助我。 感谢

1 个答案:

答案 0 :(得分:5)

好的,首先:请注意,在你的XML属性中没有引用,因此.NET的标准XML处理将无法读取开箱即用的内容 - 我只是纠正了那些以编写下面的解决方案。

var original = XDocument.Parse(/* your XML as string */);

var normalized = new XDocument(original);

foreach (var phraseNode in normalized.Root.Elements("phrase"))
{
   phraseNode.Elements().Remove();
   int ansNo = 1;

   foreach(var answer in original.Root
                                 .Elements("phrase")
                                 .Single(p => p.Attribute("permutation").Value
                                            == phraseNode.Attribute("permutation").Value)
                                 .Elements("ans"))
   {
      var groupedWords = answer.Elements("word")
                               .GroupBy(w => w.Attribute("set").Value)
                               .ToArray();
      var newAnswers = groupedWords.Skip(1)
                                   .Aggregate(
                                     groupedWords[0].Select(w => Enumerable.Repeat(w, 1)),
                                     (combinations, newWords) =>
                                         combinations.Join(newWords,
                                                           c => 1,
                                                           w => 1,
                                                           (c, w) => c.Concat(new[] { w })));
      foreach (var newAnswer in newAnswers)
      {
         var ansNode = new XElement("ans", new XAttribute("number", ansNo++));
         ansNode.Add(newAnswer.Select(w => new XElement(w)).ToArray());
         phraseNode.Add(ansNode);
      }
   }
}

如果您不了解LINQ to XML,那么一开始可能会有点吓人;希望通过一些轻松的阅读或先验知识,唯一更复杂的(相对来说当然!)位可能是生成排列的实际代码(newAnswers var初始化的部分) - 你可以采用面值或者尝试更多地了解LINQ如何加入工作。

另外 - 请注意,这并没有考虑任何重型优化;在99,99%的案例中,这应该不是一个问题。