2013-12-18 31 views
6

我有一些XML表示例如4組成員(A,B,C,D)之間的排列。假設A = {A1,A2},B = {B1},C = {C1,C2}和D = {D1,D2,D3},但是當前的XML不正常,因爲這些成員以非規則的方式組合回答。 「set」屬性顯示集合的名稱,「member」顯示每個集合的每個成員。此XML如下所示:正常化的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喜歡如以下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> 

我希望我的問題保持清醒,你可以幫助我。 謝謝

回答

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,這可能有點嚇人,希望有一些光讀或先前的知識,唯一更復雜的(當然是相對當然!)位可能是產生排列的實際代碼(var初始化的部分) - 您可以採取面值或嘗試閱讀關於LINQ如何加入的更多信息。

另外 - 請注意,這是沒有寫任何重型優化的想法;在99,99%的情況下,這不應該成爲一個問題。