使用linq从我的xml中获取数据c#

时间:2017-05-23 18:45:36

标签: c# xml linq

我想使用linq从我的xml文档中获取数据(由于它是从外部程序生成的,我无法更改此XML)。出于某种原因,_dup_check_lvl_inv_doc_type为空。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Data.SqlClient; 
using System.Xml.Linq; 

namespace ETrans 
{ 
    public class Edata 
    { 


        List<Edata> invoice = new List<Edata>(); 

        public string _dup_check_lvl { get; private set; } 

        public string _inv_doc_type { get; private set; } 





        public void get_invoice_data() 
        { 
            XDocument doc = XDocument.Load("test.xml"); 
            var invoice_data = doc.Root 
                                .Elements("Invoice") 
                                .Select(x => new Edata 
                                { 
                                    _inv_doc_type = (string)x.Attribute("Check_Level").Value, 
                                    _dup_check_lvl = (string)x.Attribute("Document_Type").Value 
                                }) 
                                .ToList(); 


            Console.WriteLine(_dup_check_lvl); 
            Console.WriteLine(_inv_doc_type); 
        } 
    } 
} 

my xml doc

<Invoice> 
  <Check_Level>2</Check_Level> 
  <Document_Type>RE</Document_Type> 
<Invoice> 

2 个答案:

答案 0 :(得分:2)

这应该更好:

var invoice_data = doc.Elements("Invoice")
                     .Select(x => new Edata  
                     {
                         _inv_doc_type = x.Element("Check_Level").Value,
                         _dup_check_lvl = x.Element("Document_Type").Value
                     })
                     .ToList();

Document_TypeCheck_Level是元素,而不是属性。此外,这假设该文件将具有多个Invoice元素,这将违反XML格式。

因此,考虑到XML文件只能有一个顶级元素,您真正想要的可能是这样的:

void Main()
{
    var edata = new Edata();
    edata.get_invoice_data();

    Console.WriteLine(edata._dup_check_lvl);
    Console.WriteLine(edata._inv_doc_type);
}


class Edata
{
    public string _inv_doc_type { get; set; }
    public string _dup_check_lvl { get; set; }

    public void get_invoice_data()
    {
         // replace with reading from file.
        var doc = XDocument.Parse(@"<Invoice> 
      <Check_Level> 2 </Check_Level>
      <Document_Type> RE </Document_Type>
    </Invoice> ");


        var invoice_data = doc.Root;    // or doc.Element("Invoice")

        _inv_doc_type = invoice_data.Element("Check_Level").Value;
        _dup_check_lvl = invoice_data.Element("Document_Type").Value;
    }
}

答案 1 :(得分:1)

这并不是你认为它做的。

.Select(x => new Edata 
{ 
    _inv_doc_type = (string)x.Attribute("Check_Level").Value, 
    _dup_check_lvl = (string)x.Attribute("Document_Type").Value 
}) 

不是在_inv_doc_type的当前实例上设置_dup_check_lvlEdata,而是创建并返回一个新的,不同的,不同的Edata对象。

对于每个&#34;发票&#34;您在XML中找到的元素,它创建并返回一个Edata实例。 Linq返回所有Edata个对象的枚举(认为发生了,您的文件只创建一个)。然后,您在该枚举上调用ToList()将其转换为List<Edata>。最后一步并非绝对必要。

试试这个:

public void get_invoice_data() 
{ 
    XDocument doc = XDocument.Load("test.xml"); 

    var invoice_data = 
        doc.Root 
        .Elements("Invoice") 
        .Select(x => new Edata 
        { 
            _inv_doc_type = (string)x.Attribute("Check_Level").Value, 
            _dup_check_lvl = (string)x.Attribute("Document_Type").Value 
        }) 
        ; 

    foreach (var edata in invoice_data) {
        Console.WriteLine(edata._dup_check_lvl); 
        Console.WriteLine(edata._inv_doc_type); 
    }
}

如果您可以保证XML 总是最多包含一个&#34; Invoice&#34;,并且您希望当前的Edata实例设置自己的字段单一&#34;发票&#34;,这样做:

if (invoice_data.Any()) {
    _dup_check_lvl = invoice_data.First()._dup_check_lvl;
    _inv_doc_type = invoice_data.First()._inv_doc_type;
}