XML元素规范化



我有一些XML表示4个集合(A、B、C、D)的成员之间的排列。假设A={A1,A2},B={B1},C={C1,C2}和D={D1,D2,D3},但当前的XML是不正常的,因为这些成员在每个答案中以非规则的方式组合在一起。"set"属性显示集合的名称,"member"显示每个集合的每个成员。这个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中的一个成员开始,以D中的一名成员结束,并且在它们之间仅使用集合B和C中的一员。例如,答案A1A2B1C1D2应与A1B1C1D2、A2B1C1D2分开,答案A1B1C1C2C3D1D3应与A1B1 C1D1、A1B1C1D3、A1B1C2D1、A1B1 C2D3、A1B1 C3D1和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>

我希望我的问题很清楚,你能帮助我。感谢

好的,首先:请注意,在您的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("one_answers"))
   {
      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("one_answers", new XAttribute("number", ansNo++));
         ansNode.Add(newAnswer.Select(w => new XElement(w)).ToArray());
         phraseNode.Add(ansNode);
      }
   }
}

如果您不了解LINQ to XML,一开始这可能有点吓人;希望通过一些简单的阅读或先验知识,唯一更复杂的(当然相对而言!)比特可能是生成排列的实际代码(newAnswers var初始化的部分)-你可以从表面上看,也可以试着更多地阅读LINQ如何连接工作。

此外,请注意,这篇文章并没有考虑到任何繁重的优化;在99,99%的病例中,这不应该是一个问题。

最新更新