2016-09-20 41 views
1

示例XML:
拼合複雜的XDocument不知道DOM

<Pricing> 
    <PriceGuide id="e4c3db5c"> 
    <Name>Price Guide A</Name> 
    <Products> 
     <Product id="1"> 
     <Name>Product 1</Name> 
     <Prices> 
      <Price> 
      <Region id="40">Chicago</Region> 
      <PriceLow>48</PriceLow> 
      <PriceHigh>52</PriceHigh> 
      <UnitOfMeasure>MT</UnitOfMeasure> 
      </Price> 
      <Price> 
      <Region id="71">Dallas</Region> 
      <PriceLow>45.5</PriceLow> 
      <PriceHigh>47</PriceHigh> 
      <UnitOfMeasure>MT</UnitOfMeasure> 
      </Price> 
     </Prices> 
     </Product> 
     <Product id="2"> 
     <Name>Product 2</Name> 
     <Prices> 
      <Price> 
      <Region id="40">Chicago</Region> 
      <PriceLow>48</PriceLow> 
      <PriceHigh>49</PriceHigh> 
      <UnitOfMeasure>MT</UnitOfMeasure> 
      </Price> 
      <Price> 
      <Region id="101">Los Angeles </Region> 
      <PriceLow>43</PriceLow> 
      <PriceHigh>45</PriceHigh> 
      <UnitOfMeasure>MT</UnitOfMeasure> 
      </Price> 
      <Price> 
      <Region id="71">Dallas</Region> 
      <PriceLow>45.5</PriceLow> 
      <PriceHigh>48.5</PriceHigh> 
      <UnitOfMeasure>MT</UnitOfMeasure> 
      </Price> 
     </Prices> 
     </Product> 
    </Products> 
    </PriceGuide> 
</Pricing> 



預期結果:(數據寫入到CSV文件或傾倒入一個DataTable)

Price Guide A, Product 1, Chicago, 48, 52, MT 
Price Guide A, Product 1, Dallas, 45.5, 47, MT 
Price Guide A, Product 2, Chicago, 48, 49, MT 
Price Guide A, Product 2, Los Angeles, 43, 45, MT 
Price Guide A, Product 2, Dallas, 45.5, 48.5, MT 



主要問題:
我基本上得到一個未知的XML文件,我必須顯示爲一個平坦的表。

這是我可以處理的許多文件之一的例子。 我不知道DOM提前,所以我不能做給定的節點名稱的直LINQ查詢。我試圖嘗試在DOM的背後行走,但是當你在遞歸中時,很難知道什麼時候寫出一條記錄。

額外積分:
從示例中,有時節點上有屬性。如果有屬性「id」,我想在輸出中包含該值。在這種情況下我的輸出是:提前

e4c3db5c, Price Guide A, 1, Product 1, 40, Chicago, 48, 52, MT 
e4c3db5c, Price Guide A, 1, Product 1, 71, Dallas, 45.5, 47, MT 
e4c3db5c, Price Guide A, 2, Product 2, 40, Chicago, 48, 49, MT 
e4c3db5c, Price Guide A, 2, Product 2, 101, Los Angeles, 43, 45, MT 
e4c3db5c, Price Guide A, 2, Product 2, 71, Dallas, 45.5, 48.5, MT 



感謝。

編輯:
下面的工作,但需要我提前瞭解XML結構。我期待推廣此代碼:

var details = 
from level1 in _xmlDoc.Root.Elements("PriceGuide") 
from level2 in level1.Elements("Name") 
from level3 in level2.Elements("Products") 
from level4 in level3.Elements("Product") 
from level5 in level4.Elements("Name") 
from level6 in level5.Elements("Prices") 
from level7 in level6.Elements("Price") 
from level8a in level7.Elements("Region") 
from level8b in level7.Elements("PriceLow") 
from level8c in level7.Elements("PriceHigh") 
from level8d in level7.Elements("UnitOfMeasure") 
select new 
{ 
       PriceGuideId = (string)level1.Attribute("id"), 
       PriceGuideName = (string)level2.Value, 
       ProductId = (string)level3.Attribute("id"), 
       ProductName = (string)level4.Value, 
       RegionId = (string)level8a.Attribute("id"), 
       RegionName = (string)level8a.Value, 
       PriceLow = (string)level8b.Value, 
       PriceHigh = (string)level8c.Value, 
       UnitOfMeasure = (string)level8d.Value, 
}; 

我知道它沒有多大幫助。

+0

如果您不知道DOM,您如何知道要提取哪些數據。 – Jules

+0

基本上是層次結構中每個節點的值。 (在可能的情況下拋出「id」屬性的值)。我甚至不介意有節點的XML節點的空值,但如果編碼更容易,則不需要值。 – Rumtis

+0

我添加了什麼工程,如果我硬編碼的節點名稱,但我需要一種方法來推廣的代碼。 – Rumtis

回答

0

我不知道如何在linq中做到這一點。這是一個快速和骯髒的代碼,可以運行

XmlDocument dom = new XmlDocument(); 
    dom.LoadXml("<Pricing><PriceGuide id=\"e4c3db5c\"><Name>Price Guide A</Name><Products><Product id=\"1\"><Name>Product 1</Name><Prices><Price><Region id=\"40\">Chicago</Region><PriceLow>48</PriceLow><PriceHigh>52</PriceHigh><UnitOfMeasure>MT</UnitOfMeasure></Price><Price><Region id=\"71\">Dallas</Region><PriceLow>45.5</PriceLow><PriceHigh>47</PriceHigh><UnitOfMeasure>MT</UnitOfMeasure></Price></Prices></Product><Product id=\"2\"><Name>Product 2</Name><Prices><Price><Region id=\"40\">Chicago</Region><PriceLow>48</PriceLow><PriceHigh>49</PriceHigh><UnitOfMeasure>MT</UnitOfMeasure></Price><Price><Region id=\"101\">Los Angeles </Region><PriceLow>43</PriceLow><PriceHigh>45</PriceHigh><UnitOfMeasure>MT</UnitOfMeasure></Price><Price><Region id=\"71\">Dallas</Region><PriceLow>45.5</PriceLow><PriceHigh>48.5</PriceHigh><UnitOfMeasure>MT</UnitOfMeasure></Price></Prices></Product></Products></PriceGuide></Pricing>"); 

    List<KeyValuePair<int, String>> result = FlattenXML(dom.DocumentElement, "", 0); 
    var q = result.Where(c => c.Key == result.Max(b => b.Key)).Select(b => b.Value.Substring(0, b.Value.Length - 1)).ToArray(); 

    Console.WriteLine(String.Join(System.Environment.NewLine, q)); 

    private List<KeyValuePair<int, String>> FlattenXML(XmlElement node, String parent, int level) 
    { 
     List<KeyValuePair<int, String>> result = new List<KeyValuePair<int, String>>(); 
     String detail = ""; 

     if (node.HasAttribute("id")) 
      parent += node.Attributes["id"].InnerText + ","; 

     if (node.InnerText == node.InnerXml && node.InnerText != "") 
     { 
      parent += node.InnerText + ","; 
     } 

     foreach (XmlElement child in node.ChildNodes) 
     { 
      if (child.InnerText == child.InnerXml && child.InnerText != "") 
      { 
       detail += child.InnerText + ","; 
       level++; 
      } 

      if (child.FirstChild != child.LastChild) 
      { 
       List<KeyValuePair<int, String>> childResult = FlattenXML(child, parent + detail, level); 
       result.AddRange(childResult); 
      } 
     } 
     result.Add(new KeyValuePair<int, String>(level, parent + detail)); 
     return result; 
    } 
+0

看起來很有希望。非常感謝你。我將在一些示例XML文件上進行測試,並在明天之前更新此問題。 – Rumtis