2012-05-25 52 views
0

對不起,這篇很長的文章....但我從這個任務頭痛。Xml簡化/提取不同的值 - 可能的LINQ

我有一英里長的XML文檔,我需要提取一個列表,使用不同的值,並通過轉換爲網頁。

我已經完成了使用xslt和keys的任務,但是這個努力迫使服務器跪下。

描述: 數以百計的產品在xml中,所有產品都帶有大量的命名和id'ed分類,所有類別至少有一個子分類與名稱和id。

的類別與ID唯一,所有的子類別內的類別中唯一:

簡化的例子形成巨大的文件(離開我們的噸的信息與任務無關):

<?xml version="1.0" encoding="utf-8"?> 
<root> 
<productlist> 
<product id="1"> 
<name>Some Product</name> 
<categorylist> 
<category id="1"> 
<name>cat1</name> 
<subcategories> 
<subcat id="1"> 
<name>subcat1</name> 
</subcat> 
<subcat id="2"> 
<name>subcat1</name> 
</subcat> 
</subcategories> 
</category> 
<category id="2"> 
<name>cat1</name> 
<subcategories> 
<subcat id="1"> 
<name>subcat1</name> 
</subcat> 
</subcategories> 
</category> 
<category id="3"> 
<name>cat1</name> 
<subcategories> 
<subcat id="1"> 
<name>subcat1</name> 
</subcat> 
</subcategories> 
</category> 
</categorylist> 
</product> 
<product id="2"> 
<name>Some Product</name> 
<categorylist> 
<category id="1"> 
<name>cat1</name> 
<subcategories> 
<subcat id="2"> 
<name>subcat2</name> 
</subcat> 
<subcat id="4"> 
<name>subcat4</name> 
</subcat> 
</subcategories> 
</category> 
<category id="2"> 
<name>cat2</name> 
<subcategories> 
<subcat id="1"> 
<name>subcat1</name> 
</subcat> 
</subcategories> 
</category> 
<category id="3"> 
<name>cat3</name> 
<subcategories> 
<subcat id="1"> 
<name>subcat1</name> 
</subcat> 
</subcategories> 
</category> 
</categorylist> 
</product> 
</productlist> 
</root> 

DESIRED結果:

<?xml version="1.0" encoding="utf-8"?> 
<root> 
<maincat id="1"> 
<name>cat1</name> 
<subcat id="1"><name>subcat1</name></subcat> 
<subcat id="2"><name>subcat2</name></subcat> 
<subcat id="3"><name>subcat3</name></subcat> 
</maincat> 
<maincat id="2"> 
<name>cat2</name> 
<subcat id="1"><name>differentsubcat1</name></subcat> 
<subcat id="2"><name>differentsubcat2</name></subcat> 
<subcat id="3"><name>differentsubcat3</name></subcat> 
</maincat> 
<maincat id="2"> 
<name>cat2</name> 
<subcat id="1"><name>differentsubcat1</name></subcat> 
<subcat id="2"><name>differentsubcat2</name></subcat> 
<subcat id="3"><name>differentsubcat3</name></subcat> 
</maincat> 
</root> 

從2000產品產生10個類別,有從5到15秒(原來的意願ubcategories)試圖

事情:

  1. XSLT的鑰匙 - 工作正常,但pooooor性能
  2. 使用LINQ各地玩過:

     IEnumerable<XElement> mainCats = 
           from Category1 in doc.Descendants("product").Descendants("category") select Category1; 
    
          var cDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root")); 
          cDoc.Root.Add(mainCats); 
          cachedCategoryDoc = cDoc.ToString(); 
    

    結果是一個 「只有類別」(不不同的分類值或子分類)

對此應用了相同的xlst,並獲得了相當好的性能.....但仍然遠不能使用...

我可以在linq語句中應用某種魔術來獲得所需的輸出嗎?

好人緣的卡車出去,可以指向我DET正確的方向的人..

//斯蒂恩

注:

  • 我不是停留在使用LINQ/XDocument如果有人有更好的選擇
  • 目前在.net 3.5上,如果需要可以切換到4
+0

感謝您的主管回覆!上週假期前我沒有時間去嘗試...... – Steen

+0

事實證明,我們的開發服務器正在處理50多個站點,因此部分影響了已經實施的基於xslt的解決方案的處理。數據提供商給了我選擇在他們的服務器上進行處理和緩存......以便解決所有問題,並將性能負載從網絡服務器轉移... 但是,非常感謝回覆,upvotes所有 - 我可能會有機會嘗試其他項目上的一些:-) – Steen

回答

1

如果我理解你的問題,這是一個LINQ嘗試。

下面的查詢解析您的XML數據並創建一個表示類別幷包含該元素的子類別的自定義類型。

解析後,數據按類別ID分組,以獲得每個類別的不同子類別。

var doc = XElement.Load("path to the file"); 
var results = doc.Descendants("category") 
    .Select(cat => new 
    { 
     Id = cat.Attribute("id").Value, 
     Name = cat.Descendants("name").First().Value, 
     Subcategories = cat.Descendants("subcat") 
      .Select(subcat => new 
      { 
       Id = subcat.Attribute("id").Value, 
       Name = subcat.Descendants("name").First().Value 
      }) 
    }) 
    .GroupBy(x=>x.Id) 
    .Select(g=>new 
    { 
     Id = g.Key, 
     Name = g.First().Name, 
     Subcategories = g.SelectMany(x=>x.Subcategories).Distinct() 
    }); 

從以上結果可以用下面的代碼創建文檔:

var cdoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root")); 
cdoc.Root.Add(
    results.Select(x=> 
    { 
     var element = new XElement("maincat", new XAttribute("id", x.Id)); 
     element.Add(new XElement("name", x.Name)); 
     element.Add(x.Subcategories.Select(c=> 
     { 
      var subcat = new XElement("subcat", new XAttribute("id", c.Id)); 
      subcat.Add(new XElement("name", c.Name)); 
      return subcat; 
     }).ToArray()); 
     return element; 
    })); 
+0

嗨RePierre,請看問題的意見。 我正在沿着相同的路線工作,但一般都搞砸了......想想我可以多看或多看哪裏.. – Steen

+0

RePierre,我選擇了你的答案作爲最佳答案,而沒有嘗試它(因爲花費的時間在一個已經解決的問題上不能向客戶收費),但它似乎確實是一個完整的解決方案與IDS和所有.....和我以前寫的,它非常接近我的想象如何我的自我在我迷失在木頭之前.. – Steen

1

試試這個我做了什麼吧..屬性丟失,你可以使用的XElement構造函數

var doc = XDocument.Load(reader); 
        IEnumerable<XElement> mainCats = 
         doc.Descendants("product").Descendants("category").Select(r => 
          new XElement("maincat", new XElement("name", r.Element("name").Value), 
           r.Descendants("subcat").Select(s => new XElement("subcat", new XElement("name", s.Element("name").Value))))); 


        var cDoc = new XDocument(new XDeclaration("1.0", "utf-8", null), new XElement("root")); 
        cDoc.Root.Add(mainCats); 
        var cachedCategoryDoc = cDoc.ToString(); 

問候添加。

+0

Shoaib,請參閱問題的意見。答案看起來簡短而整潔(如有效:-) – Steen

1

這將分析XML與所有不同的子類別名稱類別的字典。它使用XPath從這個庫:https://github.com/ChuckSavage/XmlLib/

XElement root = XElement.Load(file); 
string[] cats = root.XGet("//category/name", string.Empty).Distinct().ToArray(); 
Dictionary<string, string[]> dict = new Dictionary<string, string[]>(); 
foreach (string cat in cats) 
{ 
    // Get all the categories by name and their subcat names 
    string[] subs = root 
     .XGet("//category[name={0}]/subcategories/subcat/name", string.Empty, cat) 
     .Distinct().ToArray(); 
    dict.Add(cat, subs); 
} 

或者解析爲一個語句:

Dictionary<string, string[]> dict = root 
    .XGet("//category/name", string.Empty) 
    .Distinct() 
    .ToDictionary(cat => cat, cat => root 
     .XGet("//category[name={0}]/subcategories/subcat/name", string.Empty, cat) 
     .Distinct().ToArray()); 

我給你從字典組裝您的最終XML的任務。

+0

嗨查克,請看問題的意見。該文庫看起來很有趣。在xslts中使用xpaths的能力可以多次幫助我。 – Steen