2017-04-14 17 views
0

我已篩選我的數據是這樣的IEnumerableC#LINQ來過濾XML,保持樹形層級

xDOCfiltered = xDOC 
     .Where(k => 
      (
       (k.Attribute("Object_Heading").Value.Trim() == "Author" && k.Parent.Attribute("Milestones").Value.Contains(milestone)) 
       // 
       || k.Attribute("Milestones").Value.Contains(milestone) 
      ) 

      && filterUID.IsMatch(k.Attribute("Unique_ID").Value.Trim()) 
      && GetHierarchy(k).First() == "Code" 
      ) 
     ; 

現在我才發現,原來當我用

foreach (XElement xobj in xGDMfiltered) 
{ 
... 
... 
XNode previousNode = xobj.PreviousNode; 
... 
... 

} 

我的上一個節點是指原XDOC結構,沒有過濾一個:( 我不清楚,LINQ返回的xDOCfiltered只是一個普通列表,所有的層次結構信息都丟失了?

看來是和s omehow是合乎邏輯的,linq將返回一個集合。

我打開我的結構如下

  x= XDocument.Load(myXml); 

      xDOC = x.Element("root").Descendants("record"); 

我可以過濾不知何故,仍然保持(重建)的層次? 有點像刪除所有由LINQ表達式過濾的節點?

非常感謝您提前,

PS。 我想到的第一件事是做一個過濾列表的foreach,並從x文檔中刪除這些節點,但是有一個更優雅的解決方案?

這需要幾分鐘時間,原始未過濾的文檔有> 18.000個節點!

+0

你的問題還不清楚 - 你試圖達成的目標並不明顯。如果你澄清你的問題,最好包括一個[mcve],你可能會發現有一個比你發佈的答案更簡單的方法。 –

+0

@Jon,我盡力了。我無法在此發佈18k條記錄。這個想法是,這組XElements不像原來的XML文檔那樣保留原始的嵌套層次結構。這是在用LINQ過濾之後。所以訪問node.Previous屬性是無意義的。 – orfruit

+0

我沒有要求18K記錄。我問了一個[mcve]。你必須展示的是我們可以用來理解你的問題的代表性東西。請閱讀https://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/ –

回答

0

如果有人需要這個,我通過否定所有的子句進行修復,然後一次刪除所有不匹配的節點。與foreach刪除相比,這是非常快的。

  x.Element("root").Descendants("record") // delete if 
       .Where(k => 
        !(// NEGATE so keep this kind of objects 

         // contains desired milestone 
         k.Attribute("Milestones").Value.Contains(milestone) 

         || // or 

         (k.Attribute("Object_Heading").Value.Trim() == "Author" && k.Parent.Attribute("Milestones").Value.Contains(milestone)) 
        ) 

        // or if UID is not in this format 
        || !filterUID.IsMatch(k.Attribute("Unique_ID").Value.Trim()) // and this format for UID 

        // or if first parent (except root) is not a Code 
        || GetHierarchy(k).First() != "Code" 

        ).Remove() 
       ; 

       xDOCfiltered = 
        x.Element("root").Descendants("record");