【问题标题】:XML values with same name to list要列出的具有相同名称的 XML 值
【发布时间】:2017-12-01 08:47:03
【问题描述】:

我有以下 XML,我需要将“DUE”和“RATE”映射到带有 XmlSerializer 的对象列表。可以有零到多个,并且它们总是以相同的“idx”成对出现。

<INVOICE ID="4">
    <STATUS>S</STATUS>
    <TOTAL>6230.00</TOTAL>
    <DUE idx="1">14.12.17</DUE>
    <RATE idx="1">6230.00</RATE>
</INVOICE >
<INVOICE ID="5">
    <STATUS>S</STATUS>
    <TOTAL>3270.00</TOTAL>
    <DUE idx="1">30.11.17</DUE>
    <RATE idx="1">1090.00</RATE>
    <DUE idx="2">07.12.17</DUE>
    <RATE idx="2">1090.00</RATE>
    <DUE idx="3">14.12.17</DUE>
    <RATE idx="3">1090.00</RATE>
</INVOICE>

我有以下设置,它在没有“Rate”和“Due”列表的情况下工作正常:

[Serializable]
public class UserInvoicesDto
{
    [XmlElement("INVOICE")]
    public List<UserInvoiceDto> Invoices { get; set; }
}

[Serializable, XmlRoot("INVOICE")]
public class UserInvoiceDto
{
    [XmlAttribute("id")]
    public int InvoiceId { get; set; }
    [XmlElement("TOTAL")]
    public string Total { get; set; }
}

然后我有以下课程。

[Serializable]
public class InvoicesDueDates
{
    [XmlAttribute("idx")]
    public string Id { get; set; }
    [XmlElement("DUE")]
    public string DueDate { get; set; }
    [XmlElement("RATE")]
    public string Rate { get; set; }
}

有没有可能?

【问题讨论】:

标签: .net xml xmlserializer


【解决方案1】:

如果您只需要反序列化,则可以使用XmlSerializer 对以下类型进行反序列化:

[XmlRoot(ElementName = "DUE")]
public class DueDTO
{
    [XmlAttribute(AttributeName = "idx")]
    public string Idx { get; set; }
    [XmlText]
    public string Text { get; set; }
}

[XmlRoot(ElementName = "RATE")]
public class RateDTO
{
    [XmlAttribute(AttributeName = "idx")]
    public string Idx { get; set; }
    [XmlText]
    public decimal Text { get; set; }
}

[XmlRoot(ElementName = "INVOICE")]
public partial class InvoicesDTO
{
    [XmlAttribute(AttributeName = "ID")]
    public string Id { get; set; }
    [XmlElement(ElementName = "STATUS")]
    public string Status { get; set; }
    [XmlElement(ElementName = "TOTAL")]
    public decimal Total { get; set; }

    [XmlElement(ElementName = "DUE")]
    public List<DueDTO> Due { get; set; }
    [XmlElement(ElementName = "RATE")]
    public List<RateDTO> Rate { get; set; }
}

然后,要将 RateDue 列表组合成一个 InvoicesDueDates 集合,您可以使用 LINQ,例如如下:

public partial class InvoicesDTO
{
    public InvoicesDueDates[] InvoicesDueDates
    {
        get
        {
            // To make suure we handle cases where only a Rate or Due item of a specific index is present,
            // perform left outer joins with all indices on both Rate and Due.
            // https://docs.microsoft.com/en-us/dotnet/csharp/linq/perform-left-outer-joins
            var query = from i in Due.Select(d => d.Idx).Concat(Rate.Select(r => r.Idx)).Distinct()
                        join due in Due on i equals due.Idx into dueGroup
                        // Throw an exception if we have more than one due item for a given index
                        let due = dueGroup.SingleOrDefault()
                        join rate in Rate on i equals rate.Idx into rateGroup
                        // Throw an exception if we have more than one rate item for a given index
                        let rate = rateGroup.SingleOrDefault()
                        select new InvoicesDueDates { Id = i, DueDate = due == null ? null : due.Text, Rate = rate == null ? (decimal?)null : rate.Text };
            return query.ToArray();
        }
    }
}

public class InvoicesDueDates
{
    public string Id { get; set; }
    public string DueDate { get; set; }
    public decimal? Rate { get; set; }
}

注意事项:

  • 此解决方案利用了这样一个事实:当XmlSerializer 反序列化List&lt;T&gt; 属性并遇到与其他元素交错的列表元素时,它会将遇到的每个列表元素追加到不断增长的列表。

  • 如果您重新序列化 InvoicesDTO,结果将如下所示:

      <INVOICE ID="5">
        <STATUS>S</STATUS>
        <TOTAL>3270.00</TOTAL>
        <DUE idx="1">30.11.17</DUE>
        <DUE idx="2">07.12.17</DUE>
        <DUE idx="3">14.12.17</DUE>
        <RATE idx="1">1090.00</RATE>
        <RATE idx="2">1090.00</RATE>
        <RATE idx="3">1090.00</RATE>
      </INVOICE>
    

    请注意,所有信息都已保留并重新序列化,但 &lt;RATE&gt;&lt;DUE&gt; 序列已被分离出来。

  • 如果您需要使用交错的 &lt;RATE&gt;&lt;DUE&gt; 元素重新序列化,则必须采用不同的策略,例如来自 serializing a list of KeyValuePair to XMLXml Sequence deserialization with RestSharp 的策略。

  • 我使用 https://xmltocsharp.azurewebsites.net/ 自动生成 DTO 类,然后修改它们以适应我的命名争用。

工作示例.Net fiddle

【讨论】:

  • 非常感谢。这让我朝着正确的方向前进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多