簡體   English   中英

C#XML序列化刪除包裝器元素

[英]C# XML Serialization removing wrapper element

我寫這封信是因為XmlSerializer遇到問題。 我想要以下格式的XML:

<?xml version="1.0" encoding="utf-8"?>
<RootXML>
    <e-Invoice>
      <Version>1.03</Version>
    </e-Invoice>
    <TradeInvoice>
        <Id>1</Id>
        <Value>100</Value>
    </TradeInvoice>
    <e-Invoice>
      <Version>1.03</Version>
    </e-Invoice>
    <TradeInvoice>
        <Id>2</Id>
        <Value>200</Value>
    </TradeInvoice>
    <e-Invoice>
        <Version>1.03</Version>
    </e-Invoice>
    <TradeInvoice>
        <Id>3</Id>
        <Value>300</Value>
    </TradeInvoice>
</RootXML>

因此,我創建了以下類。

[XmlRoot("RootXML")]
public class Root
{
    public Root()
    {
        RootBodies = new List<RootBody>();
    }

    [XmlElement("e-Invoice")]
    public List<RootBody> RootBodies { get; set; }
}

public class RootBody
{
    public RootBody()
    {
        TradeInvoice = new TradeInvoice();
        EInvoiceInfo = new Version(); ;
    }

    [XmlElement("e-Invoice")]
    public Version EInvoiceInfo { get; set; }

    [XmlElement("TradeInvoice")]
    public TradeInvoice TradeInvoice { get; set; }
}

public class Version
{
    [XmlElement("Version")]
    public string Version { get; set; }
}

public class TradeInvoice
{
    [XmlElement("Id")]
    public int Id { get; set; }
    [XmlElement("Value")]
    public int Value { get; set; }
}

我在刪除包裝元素時遇到了問題(刪除RootBody)。 我讀過類似這樣的話題的鏈接 但這不能解決我的問題。

在進行實際解釋之前,讓我指出一些非常重要的事情:

  • 這種XML的設計不是很好,並且會引起很多其他問題(我想實際上比這復雜得多)。
  • 命名約定不一致( e-InvoiceTradeInvoce
  • 版本號看起來不合適,請確保這確實是他們(無論要求您執行此操作)是他們想要的,然后再花更多的時間。
  • 該XML 沒有定義名稱空間 (也可能沒有XSDDTD
  • 看看Google的XML設計指南 您會意識到還有很多改進的空間。

有很多不同的方法可以做到這一點,這只是其中之一。 我建議您改為與負責此設計的人員聯系,並嘗試改變主意。

由於您要在沒有包裝元素的情況下序列化e-InvoiceTradeInvoce ,但仍保持元素的順序(因為它們屬於同一類),因此需要確保它們具有公共基類,以便可以從同一集合進行序列化。

這個抽象的Invoice類只是通過XmlInclude屬性告訴序列化程序應該在序列化過程中包括哪些類。

[XmlInclude(typeof(EInvoice))]
[XmlInclude(typeof(TradeInvoice))]
public abstract class Invoice
{
}

您的實際課堂基本保持不變

[XmlRoot("e-Invoice")]
public class EInvoice : Invoice
{
    [XmlElement("Version")]
    public string Version { get; set; }
}

[XmlRoot("TradeInvoice")]
public class TradeInvoice : Invoice
{
    [XmlElement("Id")]
    public int Id { get; set; }
    [XmlElement("Value")]
    public int Value { get; set; }
}

您的數據類不再需要任何與XML相關的屬性,因為與現在一樣,它不能直接序列化為該格式。

public class InvoicePair
{
    public InvoicePair(EInvoice eInvoice, TradeInvoice tradeInvoice)
    {
        TradeInvoice = tradeInvoice;
        EInvoiceInfo = eInvoice;
    }

    public EInvoice EInvoiceInfo { get; set; }

    public TradeInvoice TradeInvoice { get; set; }
}

您的Root類必須進行一些簡化。 既然我們要EInvoceTradeInvoice在同一水平元素,但混合在一起,我們需要把它們放在同一個收藏。 XmlElement屬性將告訴序列化程序如何在不依賴xsi:type屬性的情況下處理不同類型的元素。

[XmlRoot("RootXML")]
public class Root
{
    public Root()
    {
        RootBodies = new List<Invoice>();
    }

    [XmlElement(Type = typeof(EInvoice), ElementName = "e-Invoice")]
    [XmlElement(Type = typeof(TradeInvoice), ElementName = "TradeInvoice")]
    public List<Invoice> RootBodies { get; set; }
}

在這一點上,序列化非常簡單。 只需將所有元素一個接一個地添加到元素集合中:

public static void Serialize(IEnumerable<InvoicePair> invoices, Stream stream)
{
    Root root = new Root();
    foreach (var invoice in invoices)
    {
        root.RootBodies.Add(invoice.EInvoiceInfo);
        root.RootBodies.Add(invoice.TradeInvoice);
    }

    XmlSerializer serializer = new XmlSerializer(typeof(Root));
    serializer.Serialize(stream, root);
}

反序列化也不是很困難,但是很容易出錯,並做出許多假設:

public static IEnumerable<InvoicePair> Deserialize(Stream stream)
{
    XmlSerializer serializer = new XmlSerializer(typeof(Root));
    Root root = serializer.Deserialize(stream) as Root;

    for (int i = 0; i < root.RootBodies.Count; i += 2)
    {
        yield return new InvoicePair(
            (EInvoice) root.RootBodies[i], 
            (TradeInvoice) root.RootBodies[i+1]
        );
    }
}

這是一個工作中的演示小提琴,它輸出XML

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM