2013-08-06 163 views
1
<ndActivityLog repositoryId="AA-AAAA1AAA" repositoryName="Company Name" startDate="2013-07-05" endDate="2013-07-06"> 
    <activity date="2013-07-05T06:42:35" name="open" host="00.00.00.00"> 
     <user id="[email protected]" name="Joe Bloggs" memberType="I" /> 
     <storageObject docId="0000-0000-0000" name="Opinion" size="356864" fileExtension="doc"> 
      <cabinet name="Client and Matters">NG-5MIYABBV</cabinet> 
      <DocumentType>Legal Document</DocumentType> 
      <Author>Joe Bloggs</Author> 
      <Matter>1001</Matter> 
      <Client>R1234</Client> 
     </storageObject> 
    </activity> 
</ndActivityLog> 

這是XML的一個示例。文檔中有大約4000個「活動」元素,內容不同。有些人擁有「客戶」和「重要」元素,其他人則沒有。把它想象成一個表格,這些將是空白單元格,但列標題仍然存在。C#中的複雜嵌套XML解析#

我基本上需要解析這個SQL數據庫,保持數據結構。最重要的是,如果某個元素在某些示例中不存在,則需要引用該事實並將其保留爲「空白單元格」。

var doc = XDocument.Load(path + "\\" + file + ".xml"); 

     var root = doc.Root; 
     foreach (XElement el in root.Elements()) 
     { 

       // Console.WriteLine(el.Nodes()); 
       // Console.WriteLine(el.Value); 
       //Console.WriteLine(" Attributes:"); 
       foreach (XAttribute attr in el.Attributes()) 
       { 

        Console.WriteLine(attr); 
       // Console.WriteLine(el.Elements("id")); 


       } 

      Console.WriteLine("---------------------------"); 

      // foreach (XElement element in el.Elements()) 
     // { 

    //   Console.WriteLine(" {0}: {1}", element.Name, element.Value); 
     //  } 

      } 
      //hold console open 
      Console.ReadLine(); 

     } 

到目前爲止的代碼。輸出如下所示

date="2013-07-06T17:07:42" 
name="open" 
host="213.146.142.50 

我基本上需要的每一條信息將被提取,所以我可以將它們存儲在實質上是一個表的佈局。 我對使用XML解析合理新,所以任何幫助,將不勝感激。

+1

是否有一個特殊的原因,您想手動解析它?爲什麼不創建相應的c#類並將其反序列化爲這些類? – derape

+1

爲什麼你不序列化它http://msdn.microsoft.com/en-us/library/58a18dwa.aspx – Krishna

+0

@derape我是在假設,我必須做'XDocument'或LINQ –

回答

0

只有您知道允許的屬性名稱cabinet ... Client。簡單的蠻力方法是提取每個期望的屬性,然後你會知道哪些是缺少的,並可以將單元格設置爲空。 Foreach只會遍歷每個元素上存在的內容 - 它不能猜測丟失的元素。

0

我想你可以通過以下方式解決問題:

  1. 您創建一個名爲BaseNode類。

  2. 您創建的所有實體類型的

  3. 創建了基於節點上的一組規則擴展BaseNode類確定首選的實體類型

  4. 您在創建generateEntity方法你BaseNode類。

  5. 使用此算法(這不是代碼,所以不要試圖編譯)

parseXML(節點)

for each node in node do 

    BaseNode.generateEntity(node.input) 

    if (node.hasChildren()) 

     parseXML(node) 

    end if 

end for 

末parseXML

當然,你必須存儲和解析生成的實體。

0

說這是最好的或正確的方法來解決您的特定問題,但是,我提供它的你可以做什麼刪節例子(因此處理缺乏異常/錯誤等)。

namespace so.consoleapp 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Xml.Linq; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var doc = XElement.Load("file.xml"); 
      var activityElements = doc.Elements("activity"); 

      ICollection<Activity> collectionOfActivities = new List<Activity>(); 
      foreach (var activityElement in activityElements) 
      { 
       var storageObjectElement = activityElement.Element("storageObject"); 

       string clientElement = null; 
       if (storageObjectElement.Element("Client") != null) 
       { 
        clientElement = storageObjectElement.Element("Client").Value; 
       } 

       var newStorageObject = new StorageObject 
       { 
        Client = clientElement, 
        Author = storageObjectElement.Element("Author").Value 
       }; 

       var userElement = activityElement.Element("user"); 
       var newUser = new User 
       { 
        Id = userElement.Attribute("id").Value, 
        Name = userElement.Attribute("name").Value, 
        MemberType = userElement.Attribute("memberType").Value 
       }; 

       collectionOfActivities.Add 
       (
        new Activity 
        { 
         Date = activityElement.Attribute("date").Value, 
         Name = activityElement.Attribute("name").Value, 
         Host = activityElement.Attribute("host").Value, 
         User = newUser, 
         StorageObject = newStorageObject 
        } 
       ); 
      } 

      Console.ReadLine(); 
     } 
    } 

    class Activity 
    { 
     public string Date 
     { 
      get; 
      set; 
     } 

     public string Name 
     { 
      get; 
      set; 
     } 

     public string Host 
     { 
      get; 
      set; 
     } 

     public User User 
     { 
      get; 
      set; 
     } 

     public StorageObject StorageObject 
     { 
      get; 
      set; 
     } 
    } 

    class User 
    { 
     public string Id 
     { 
      get; 
      set; 
     } 

     public string Name 
     { 
      get; 
      set; 
     } 

     public string MemberType 
     { 
      get; 
      set; 
     } 
    } 

    class StorageObject 
    { 
     public string Client 
     { 
      get; 
      set; 
     } 

     public string Author 
     { 
      get; 
      set; 
     } 
    } 
} 
0

嘗試類似的東西。創建一個新的Windows Forms Application,一個DataGrid控件添加到窗體和代碼背後象下面這樣:

private void Form1_Load(object sender, EventArgs e) 
     { 
      populate_datagrid(dataGridView1); 
     } 

     private void populate_datagrid(DataGridView dataGridView1) 
     { 
      String xml_string = @"<ndActivityLog repositoryId=""AA-AAAA1AAA"" repositoryName=""Company Name"" startDate=""2013-07-05"" endDate=""2013-07-06""> 
            <activity date=""2013-07-05T06:42:35"" name=""open"" host=""00.00.00.00""> 
             <user id=""[email protected]"" name=""Joe Bloggs"" memberType=""I"" /> 
             <storageObject docId=""0000-0000-0000"" name=""Opinion"" size=""356864"" fileExtension=""doc""> 
              <cabinet name=""Client and Matters"">NG-5MIYABBV</cabinet> 
              <DocumentType>Legal Document</DocumentType> 
              <Author>Joe Bloggs</Author> 
              <Matter>1001</Matter> 
              <Client>R1234</Client> 
             </storageObject> 
            </activity> 
            <activity date=""2013-06-05T06:42:35"" name=""close"" host=""00.00.00.00""> 
             <user id=""[email protected]"" name=""abc"" memberType=""I"" /> 
             <storageObject docId=""0000-0000-0000"" name=""Opinion"" size=""25630"" fileExtension=""doc""> 
              <cabinet name=""Client and Matters"">NG-5MIYABBV</cabinet> 
              <DocumentType>Legal Document</DocumentType> 
              <Author>abc</Author> 
              <Client>R1234</Client> 
             </storageObject> 
            </activity> 
            <activity date=""2013-06-05T06:42:35"" name=""unknown"" host=""00.00.00.00""> 
             <user id=""[email protected]"" name=""bca"" memberType=""I"" /> 
             <storageObject docId=""0000-0000-0000"" name=""Opinion"" size=""45875"" fileExtension=""doc""> 
              <cabinet name=""Client and Matters"">NG-5MIYABBV</cabinet> 
              <DocumentType>Legal Document</DocumentType> 
              <Author>bca</Author> 
              <Matter>1001</Matter> 
             </storageObject> 
            </activity> 
            <activity date=""2013-06-05T06:42:35"" name=""open"" host=""00.00.00.00""> 
             <user id=""[email protected]"" name=""cab"" memberType=""I"" /> 
             <storageObject docId=""0000-0000-0000"" name=""Opinion"" size=""45875"" fileExtension=""doc""> 
              <cabinet name=""Client and Matters"">NG-5MIYABBV</cabinet> 
              <DocumentType>Legal Document</DocumentType> 
             </storageObject> 
            </activity> 
           </ndActivityLog>"; 

      var query = from XElement c in System.Xml.Linq.XElement.Parse(xml_string).Descendants("activity") 
         select new 
         { 
          user = c.Elements("user").First().Attribute("name").Value, 
          author = c.Descendants("Author").Count() > 0 ? c.Descendants("Author").First().Value : "n/a", 
          matter = c.Descendants("Matter").Count() > 0 ? c.Elements("Matter").First().Value : "n/a" 
         }; 

      dataGridView1.DataSource = query.ToList(); 

     } 

希望這有助於。