【问题标题】:Read a XML with Linq C# using where condition使用 where 条件使用 Linq C# 读取 XML
【发布时间】:2020-05-09 09:32:26
【问题描述】:

我尝试为我的业务提供一点服务,但它不起作用。

<item>
<key>12323</key>
<summary></summary>
<reporter username="12313asdf">1232 asdf iii</reporter>
   <cusomfields>
        <customfield id="customfield_37723" key="xyz">
          <customfieldname>First Name</customfieldname>
          <customfieldvalues>
            <customfieldvalue>Klaus</customfieldvalue>
          </customfieldvalues>
        </customfield>
//...many customfields
   </customfields>
</item>

我用这段代码创建了一个 c# 方法 -> 但它不起作用:(

XDocument doc = XDocument.Load(fileName);

var obj = (from c in doc.Descendants("item")
          select new ServiceRequest_NewUser()
          {
           TicketID = c.Element("key").Value,
           Summary = c.Element("summary").Value,
           ReporterNT = c.Element("reporter").Attribute("username").Value,
           ReporterFull = c.Element("reporter").Value,
           FirstName = (from f in c.Descendants("customfields")
                        where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
                        select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
           }).ToList();

foreach (var i in obj)
{
 var test = i.FirstName;
 Console.WriteLine($"{i.TicketID} {i.Summary} {i.ReporterNT} {i.ReporterFull} {i.FirstName}");
}

我的错在哪里?我在评论标签中做了一个替代版本的代码。我需要输出值“Klaus”。

提前感谢您的帮助。

【问题讨论】:

  • 嗨,我决定用序列化处理整个事情。这不仅聪明而且效率更高。无论如何感谢您的帮助。

标签: c# xml linq-to-xml


【解决方案1】:

如果您希望在 FirstName 中看到 Klaus,您应该这样写:

            var obj = (from c in doc.Elements("item")
                select new
                {
                    TicketID = c.Element("key")?.Value,
                    Summary = c.Element("summary")?.Value,
                    ReporterNT = c.Element("reporter")?.Attribute("username")?.Value,
                    ReporterFull = c.Element("reporter").Value,
                    FirstName = (from f in c.Descendants("customfields")
                        where f.Element("customfield")?.Attribute("id")?.Value == "customfield_37723"
                        select f.Descendants("customfieldvalues").FirstOrDefault()?.Value).FirstOrDefault()
                }).ToList();

【讨论】:

  • 感谢您的及时回复。看起来比我的好多了:) 现在我收到以下消息: System.NullReferenceException: '对象引用未设置为对象的实例。 System.Xml.Linq.XContainer.Element(...) 返回 null。
  • 我修复了。再试一次。
  • 现在我没有收到错误 - 但不幸的是,该值不是 Klaus,它应该在我的列表中。但我认为我做错了:(我忘记了“customfield”周围的标签 - 我编辑了我的代码 - 你能再帮我一次吗:)?
  • 您的 xml cusomfields 中有错字。
  • 不要使用“价值”。当值为空时,它会给出异常。而是强制转换为该值。
【解决方案2】:

尝试以下:

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

namespace ConsoleApplication1
{
    class Program
    {
        const string FILENAME = @"c:\temp\test.xml";
        static void Main(string[] args)
        {
            XDocument doc = XDocument.Load(FILENAME);

            List<Item> items = doc.Descendants("item").Select(x => new Item()
            {
                key = (string)x.Element("key"),
                summary = (string)x.Element("summary"),
                usernameText = (string)x.Element("reporter"),
                username = (string)x.Element("reporter").Attribute("username"),
                fields = x.Descendants("customfield").Select(y => new Field()
                {
                    id = (string)y.Attribute("id"),
                    key = (string)y.Attribute("key"),
                    name = (string)y.Element("customfieldname"),
                    values = y.Descendants("customfieldvalue").Select(z => (string)z).ToList()
                }).ToList()
            }).ToList();

            List<Item> customfield_37723 = items.Where(x => x.fields.Any(y => y.id == "customfield_37723")).ToList();

            foreach (Item item in customfield_37723)
            {
                Console.WriteLine("Item : key = '{0}', summary = '{1}', username Text = '{2}', username = '{3}'",
                    item.key, item.summary, item.usernameText, item.username);

                foreach (Field field in item.fields)
                {
                    Console.WriteLine("     Field : id = '{0}', key = '{1}', name = '{2}', values = '{3}'",
                        field.id, field.key, field.name, string.Join(",", field.values));
                }
            }

            Console.ReadLine();
        }
    }
    public class Item
    {
        public string key { get; set; }
        public string summary { get; set; }
        public string usernameText { get; set; }
        public string username { get; set; }
        public List<Field> fields { get; set; }

    }
    public class Field
    {
        public string id { get; set; }
        public string key { get; set; }
        public string name { get; set; }
        public List<string> values { get; set; }
    }
}

【讨论】:

  • 谢谢,但它对我不起作用。我需要这样的 s.th 作为输出: foreach (var i in obj) { Console.WriteLine($"{i.TicketID} {i.Summary} {i.ReporterNT} {i.ReporterFull} {i.FirstName}" );名字不是记者的名字。
  • 谢谢,现在我有了所有“castumfieldvalue”元素的列表。我只需要“castomfieldwalue”,它在元素“customfieldnvalues”中,而这又在元素“customfield”中,属性id =“customfield_37723”。属性 id 是可用于过滤的唯一键。结果应该是字符串 Firstname = Klaus。我的问题是对此进行过滤,以便获得一个包含每个 obj 的以下值的列表:TicketID、Summary、ReporterNT、ReporterFull、FirstName。
  • 也许有一个非常简单的解决方案。没有Linq?没有 XDocument?我能以某种方式很好地阅读这个难看的 2000 行 XML 文件吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
相关资源
最近更新 更多