从C#中的属性获取XML数据

时间:2015-11-14 18:44:25

标签: c# xml linq

我有一个以XML格式返回数据的API。 XML的相关部分如下所示:

<data name="Rows">
   <data Name="Row">
     <data name="CONTACT">John Smith</data>
     <data name="PHONE1">(555)123-4567</data>
   </data>
   <data Name="Row">
     <data name="CONTACT">Jim Smith</data>
     <data name="PHONE1">(555)123-6754</data>
   </data>
</data>

我可以使用以下方法获取每行的节点集合:

var query = from item in xdoc.Root.Descendants("data")
            where (string)item.Attribute("Name") == "Row"
            select item;

如果按属性过滤,则每个元素的字符串集合:

var query2 = from item in query.Elements("data")
             where (string)item.Attribute("name") == "CONTACT" 
             select item;

returns: John Smith, James Smith

但我无法弄清楚如何将每个联系人姓名和电话号码放在一起。

类似的东西:

foreach(var row in query)
{
    contact = query.???;
    phone1 = query.????;
}

3 个答案:

答案 0 :(得分:1)

您需要使用第一个查询来获取行元素的集合。然后,对于每个元素,您需要查找具有所需属性的子项:

// Find all elements  <data Name="Row">
var query = from item in xdoc.Root.Descendants("data")
     where (string)item.Attribute("Name") == "Row"
     select item;

// Loop through the elements
foreach(var row in query)
{
    // find child element, that has attribute Name="CONTACT"
    var contactElement = row.Descendants("data")
        .Where(x=>(string)x.Attribute("Name") == "CONTACT")
        .First();
    // find child element, that has attribute Name="PHONE1"
    var phoneElement = row.Descendants("data")
        .Where(x=>(string)x.Attribute("Name") == "PHONE1")
        .First();
    // get values of found elements
    var contact = contactElement.Value;
    var phone1 = phoneElement.Value;
}

上面的代码假定您将始终拥有所有元素,因此使用函数First()。如果某些元素可能丢失,则需要相应处理。

答案 1 :(得分:1)

由于在您的XML中所有节点都是var elixir = require('laravel-elixir'); require('./elixir-extensions'); elixir(function(mix) { mix.sass([ 'app.scss' ], 'public/assets/css'); mix.scripts([ '../../bower/0/index.js', '../../../node_modules/bootstrap-sass/assets/javascripts/bootstrap.js', 'app.js' ], 'public/assets/js'); mix.version(['assets/css/app.css', 'assets/js/all.js']); }); ,因此使用Descedants可能会导致意外结果,因为它会找到所有节点,无论它存在于何处。我会一步一步走: -

1)从根节点使用data查找所有元素,这将为您提供两个属性xdoc.Root.Elements("data")Name的节点。
2)现在,从步骤1中检索到的集合中,找到Row属性为dataname的第一个CONTACT
3)只需投影在步骤2中检索的项目。

PHONE1

或使用方法语法: -

 var res = from item in xdoc.Root.Elements("data")
           let ContactRow = item.Elements("data")
                            .FirstOrDefault(x => (string)x.Attribute("name") == "CONTACT")
           let PHONE1Row = item.Elements("data")
                            .FirstOrDefault(x => (string)x.Attribute("name") == "PHONE1")
           select new
                 {
                    Contact = (string)ContactRow,
                    Phone1 = (string)PHONE1Row
                 };

答案 2 :(得分:0)

或试试这个

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml =
                "<data name=\"Rows\">" +
                   "<data Name=\"Row\">" +
                     "<data name=\"CONTACT\">John Smith</data>" +
                     "<data name=\"PHONE1\">(555)123-4567</data>" +
                   "</data>" +
                   "<data Name=\"Row\">" +
                     "<data name=\"CONTACT\">Jim Smith</data>" +
                     "<data name=\"PHONE1\">(555)123-6754</data>" +
                   "</data>" +
                "</data>";

            XElement doc = XElement.Parse(xml);

            var results = doc.Descendants().Where(x => (string)x.Attribute("Name") == "Row").Select(x => new {
               contact = x.Elements().Where(y => (string)y.Attribute("name") == "CONTACT").FirstOrDefault().Value,
               phone = x.Elements().Where(y => (string)y.Attribute("name") == "PHONE1").FirstOrDefault().Value,
            }).ToList();
        }
    }
}
​