在C#中复杂的嵌套XML解析(Complex nested XML Parsing in C#)

2019-10-18 11:28发布

<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="joebloggs@email.com" 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左右的“活动”的文件中的元素,与内容不同的水平。 有些人的“客户”与“物”的元素,有的则没有。 把它像一个表,这些将是空白单元格,但列标题仍然存在。

我基本上是需要解析这到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解析,所以任何帮助,将不胜感激。

Answer 1:

只有你知道允许的属性名内阁...客户端。 简单的蛮力,方法是将提取每个预期的属性,然后你就会知道哪些是缺失的,并且可以在电池设置为空。 的foreach只会遍历的是存在于每个元素 - 它不能猜测没有的部分。



Answer 2:

我想你可以解决以下方式你的问题:

  1. 您创建一个名为BaseNode类。

  2. 您创建的所有实体类型的扩展BaseNode类

  3. 您创建了基于节点的一组规则确定首选的实体类型

  4. 您创建一个在您BaseNode类generateEntity方法。

  5. 您可以使用此算法(这不是代码,所以不要试图编译)

parseXML(节点)

for each node in node do

    BaseNode.generateEntity(node.input)

    if (node.hasChildren())

        parseXML(node)

    end if

end for

比parseXML

当然,你必须存储和解析生成的实体。



Answer 3:

不是说这是解决您的特定问题的最佳或正确的方法,但是,我提供它的你可以做什么删节例子(因此缺乏异常/错误处理等)。

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;
        }
    }
}


Answer 4:

尝试类似的东西。 创建一个新的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=""joebloggs@email.com"" 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=""abc@bca.com"" 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=""bca@abc.com"" 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=""cab@abc.com"" 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();

        }

希望这可以帮助。



文章来源: Complex nested XML Parsing in C#