如何迭代 LINQ-to-XML 查询返回的对象集合?

发布于 2024-09-01 21:51:26 字数 2544 浏览 7 评论 0原文

我有这个 XML:

<BillingLog>
  <BillingItem>
    <date-and-time>2003-11-04</date-and-time>
    <application-name>Billing Service</application-name>
    <severity>Warning</severity>
    <process-id>123</process-id>
    <description>Timed out on a connection</description>
    <detail>Timed out after three retries.</detail>
  </BillingItem>
  <BillingItem>
    <date-and-time>2010-05-15</date-and-time>
    <application-name>Callback Service</application-name>
    <severity>Error</severity>
    <process-id>456</process-id>
    <description>Unable to process callback</description>
    <detail>Reconciliation timed out after two retries.</detail>
  </BillingItem>
</BillingLog>

我想使用 LINQ-to-XML 将其投影到单个 BillingLog 对象中包含的 BillingItem 对象的集合中。

public class BillingLog
{
    public IEnumerable<BillingItem> items { get; set; }
}

public class BillingItem
{
    public string Date { get; set; }
    public string ApplicationName { get; set; }
    public string Severity { get; set; }
    public int ProcessId { get; set; }
    public string Description { get; set; }
    public string Detail { get; set;}       
}

这是我用来投影 XML 的 LINQ 查询(包含在字符串变量 source 中)。

XDocument xdoc = XDocument.Parse(source);

var log = 
    from i in xdoc.Elements("BillingLog")
    select new BillingLog
    {
        items =
            from j in i.Descendants("BillingItem")
            select new BillingItem
            {
                Date = (string)j.Element("date-and-time"),
                ApplicationName = (string)j.Element("application-name"),
                Severity = (string)j.Element("severity"),
                ProcessId = (int)j.Element("process-id"),
                Description = (string)j.Element("description"),
                Detail = (string)j.Element("detail")
            }
    };

当我尝试使用 foreach 迭代 log 中的对象时。

foreach (BillingItem item in log)
{
Console.WriteLine ("{0} | {1} | {2} | {3} | {4} | {5}", 
                    item.Date, item.ApplicationName, 
                    item.Severity, item.ProcessId.ToString(), 
                    item.Description, item.Detail);
}   

我从 LINQPad 收到以下错误消息。

Cannot convert type 'UserQuery.BillingLog' to 'UserQuery.BillingItem'

提前致谢。

I've got this XML:

<BillingLog>
  <BillingItem>
    <date-and-time>2003-11-04</date-and-time>
    <application-name>Billing Service</application-name>
    <severity>Warning</severity>
    <process-id>123</process-id>
    <description>Timed out on a connection</description>
    <detail>Timed out after three retries.</detail>
  </BillingItem>
  <BillingItem>
    <date-and-time>2010-05-15</date-and-time>
    <application-name>Callback Service</application-name>
    <severity>Error</severity>
    <process-id>456</process-id>
    <description>Unable to process callback</description>
    <detail>Reconciliation timed out after two retries.</detail>
  </BillingItem>
</BillingLog>

That I want to project using LINQ-to-XML into a collection of BillingItem objects contained in a single BillingLog object.

public class BillingLog
{
    public IEnumerable<BillingItem> items { get; set; }
}

public class BillingItem
{
    public string Date { get; set; }
    public string ApplicationName { get; set; }
    public string Severity { get; set; }
    public int ProcessId { get; set; }
    public string Description { get; set; }
    public string Detail { get; set;}       
}

This is the LINQ query that I'm using to project the XML (which is contained in the string variable source).

XDocument xdoc = XDocument.Parse(source);

var log = 
    from i in xdoc.Elements("BillingLog")
    select new BillingLog
    {
        items =
            from j in i.Descendants("BillingItem")
            select new BillingItem
            {
                Date = (string)j.Element("date-and-time"),
                ApplicationName = (string)j.Element("application-name"),
                Severity = (string)j.Element("severity"),
                ProcessId = (int)j.Element("process-id"),
                Description = (string)j.Element("description"),
                Detail = (string)j.Element("detail")
            }
    };

When I try and iterate over the objects in log using foreach.

foreach (BillingItem item in log)
{
Console.WriteLine ("{0} | {1} | {2} | {3} | {4} | {5}", 
                    item.Date, item.ApplicationName, 
                    item.Severity, item.ProcessId.ToString(), 
                    item.Description, item.Detail);
}   

I get the following error message from LINQPad.

Cannot convert type 'UserQuery.BillingLog' to 'UserQuery.BillingItem'

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

诺曦 2024-09-08 21:51:26

这是因为您的 log 变量包含 BillingLog 对象的集合,而不是 BillingItem。您必须执行以下操作:

foreach( BillingLog l in log )
{
    foreach( BillingItem item in l.items )
    {
        Console.WriteLine( ... );
    }
}

或者,如果您最初的意图是仅选择所有 BillingItem,完全忽略其父 BillingLog,您可以像这样重写查询:

var log = 
        from l in xdoc.Elements("BillingLog")
        from j in l.Descendants("BillingItem")
        select new BillingItem
        {
            Date = (string)j.Element("date-and-time"),
            ApplicationName = (string)j.Element("application-name"),
            Severity = (string)j.Element("severity"),
            ProcessId = (int)j.Element("process-id"),
            Description = (string)j.Element("description"),
            Detail = (string)j.Element("detail")
        }

这将为您提供从所有 BillingLog 下选择的所有 BillingItems 的简单集合,而 BillingLog 本身将被完全丢弃。

That's because your log variable contains a collection of BillingLog objects, not BillingItem. You have to do something like:

foreach( BillingLog l in log )
{
    foreach( BillingItem item in l.items )
    {
        Console.WriteLine( ... );
    }
}

Alternatively, if your original intent was to just select all BillingItems, disregarding their parent BillingLogs completely, you could rewrite your query like so:

var log = 
        from l in xdoc.Elements("BillingLog")
        from j in l.Descendants("BillingItem")
        select new BillingItem
        {
            Date = (string)j.Element("date-and-time"),
            ApplicationName = (string)j.Element("application-name"),
            Severity = (string)j.Element("severity"),
            ProcessId = (int)j.Element("process-id"),
            Description = (string)j.Element("description"),
            Detail = (string)j.Element("detail")
        }

This will give you a plain collection of all BillingItemss selected from under all BillingLogs, while BillingLogs themselves will be completely discarded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文