在单个LINQ XML查询中填充类对象的方法?

时间:2015-05-12 22:12:08

标签: c# xml linq linq-to-xml

鉴于以下XML片段,有没有办法在一个LINQ语句中查询和填充类对象?由于需要选择使用属性值,这令人困惑。

<data>
 <array>
  <item key="0">
   <map>
    <item key="mrid">53030</item>
    <item key="mrtitle">GeneralFeedback</item>
   </map>
  </item>
 </array>
</data>

类别:

public class Incident
{
    public int ID { get; set; }
    public string Title { get; set; }
}

当前(工作)代码(结果是XML片段作为字符串):

var data = XDocument.Parse(result);

var id = from item in data.Descendants("item")
    where item.Attribute("key").Value == "mrid"
    select item.Value;

var title = from item in data.Descendants("item")
    where item.Attribute("key").Value == "mrtitle"
    select item.Value;

var incident = new Incident
{
    ID = Convert.ToInt32(id.FirstOrDefault()),
    Title = title.FirstOrDefault()
};

根据给出的答案,我学到了一些有用的东西,并提出了这种变化:

var incidents = data.Descendants("map")
    .Select(i => i.Descendants("item")
        .ToDictionary(m => m.Attribute("key").Value, m => m.Value))
    .Where(i => i.ContainsKey("mrid")
                && i.ContainsKey("mrtitle"))
    .Select(i => new Incident
    {
        ID = int.Parse(i["mrid"]),
        Title = i["mrtitle"]
    });

我真正喜欢的一件事是,它创建了一个IEnumerable,允许XML数据中存在多个事件。

3 个答案:

答案 0 :(得分:1)

Check out this post to learn how to convert your XML schema to a C# class Generate C# class from XML

Then you can use your new type and de-serialize your XML to a class

function projBuiltOptions(elem){

var custom_made_wrapper = $("#custom_made_wrapper");
var cms_wrapper = $("#cms_wrapper");

var id = elem.attr("id");

if(id == "custom_made") {

    custom_made_wrapper.prop({disabled:false}).show();
    cms_wrapper.prop({disabled:false}).hide();


} else if(id == "cms" ) {

    cms_wrapper.prop({disabled: false}).show();
    custom_made_wrapper.hide();


   //I would like to achieve something like this..
    custom_made_wrapper.(" input").prop({disabled: true})


}

答案 1 :(得分:1)

is there a way to both query and populate a class object in one LINQ statement?

Yes, well sorta ... and it remains quite ugly. The below "single" multi-step LINQ statement ensures only the items that belong to the same var json = require('./myJsonFile'); require('./mod1'); console.log(json); // { files: // { rootNeeded: [], // folders: [], // files: [ 'test 1', 'test 2' ], // images: [], // text: [], // unknown: [] } } element get selected. Like your code sample, it will blow up in your face if the items with the required key values are missing (or the "mrid" element is not an map).

int

It will produce the output below for your given xml input file:

var key_vals = new List<string> { "mrid", "mrtitle" };
var xdoc = XDocument.Load(@"c:\temp\test.xml");
var incidents = xdoc.Descendants("map").Select(map => {
    var items = map.Descendants("item").Where(i => key_vals.Contains(i.Attribute("key").Value));
    var idItem = items.Where(x => x.Attribute("key").Value == "mrid").First();
    var titleItem = items.Where(x => x.Attribute("key").Value == "mrtitle").First();
    return new Incident {
        ID = int.Parse(idItem.Value),
        Title = titleItem.Value
    };
});

foreach (var i in incidents)
    Console.WriteLine("ID = {0}, Title = {1}", i.ID, i.Title);

答案 2 :(得分:1)

Alex已经给出了一个完美的答案,但我觉得这更具可读性(: Where子句确保找到每个项目,具有构造事件所需的密钥。

var incidents = xdoc.Root
                    .Element("array")
                    .Elements("item")
                    .Select(i => i.Element("map")
                                  .Elements("item")
                                  .ToDictionary(m => m.Attribute("key").Value,
                                                m => m.Value))
                    .Where(i => i.ContainsKey("mrid")
                             && i.ContainsKey("mrtitle"))
                    .Select(i => new Incident
                                 {
                                     ID = int.Parse(i["mrid"]),
                                     Title = i["mrtitle"]
                                 });