XML元素规范化

7

我有一些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应分别分为A1B1C1D1,A1B1C1D3,A1B1C2D1,A1B1C2D3,A1B1C3D1和A1B1C3D3。最终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个回答

6

首先需要注意的是,您的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变量的部分)- 您可以只接受这个结果,也可以尝试更多地了解LINQ连接的工作原理。
另外,请注意,这并没有考虑任何重度优化;在99.99%的情况下,这应该不是问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接