簡體   English   中英

XmlSerializer將C#對象轉換為xml字符串

[英]XmlSerializer Convert C# object to xml string

我創建了一個C#類:

public class books {
    public int bookNum { get; set; }
    public class book {
        public string name { get; set; }
        public class record {
            public string borrowDate { get; set; }
            public string returnDate { get; set; }
        }
        public record[] records { get; set; }
    }
    public book[] books { get; set; }
}

但是當我使用XmlSerializer轉換為XML字符串時。 結果與下面的xml不同。

我的C#類有什么問題? 我想使用XmlSerializer輸出結果而不是使用XmlDocument。

有任何想法嗎? 提前致謝!

<books>
    <bookNum>2</bookNum>
    <book>
        <name>Book 1</name>
        <record>
            <borrowDate>2013-7-1</borrowDate>
            <returnDate>2013-7-12</returnDate>
        </record>
        <record>            
            <borrowDate>2013-8-1</borrowDate>
            <returnDate>2013-8-5</returnDate>
        </record>
    </book>
    <book>
        <name>Book 2</name>
        <record>
            <borrowDate>2013-6-1</borrowDate>
            <returnDate>2013-6-12</returnDate>
        </record>
        <record>            
            <borrowDate>2013-7-1</borrowDate>
            <returnDate>2013-7-5</returnDate>
        </record>
    </book>
</books>

編輯

下面是我的C#代碼和輸出結果:

books books = new books {
        bookNum = 2,
        Books = new books.book[] { 
            new books.book {  
                name = "Book1", 
                records = new books.book.record[] {
                    new books.book.record {
                        borrowDate = "2013-1-3",
                        returnDate = "2013-1-5"
                    },
                     new books.book.record {
                        borrowDate = "2013-2-3",
                        returnDate = "2013-4-5"
                    }
                }
            },
             new books.book {  
                name = "Book1", 
                records = new books.book.record[] {
                    new books.book.record {
                        borrowDate = "2013-1-3",
                        returnDate = "2013-1-5"
                    },
                     new books.book.record {
                        borrowDate = "2013-2-3",
                        returnDate = "2013-4-5"
                    }
                }
            }
        }
    };


    XmlSerializer xsSubmit = new XmlSerializer(typeof(books));

    XmlDocument doc = new XmlDocument();

    System.IO.StringWriter sww = new System.IO.StringWriter();
    XmlWriter writer = XmlWriter.Create(sww);
    xsSubmit.Serialize(writer, books);
    var xml = sww.ToString(); // Your xml
    context.Response.Write(xml);

XML:

<books>
    <bookNum>2</bookNum>
    <Books>
        <book>
            <name>Book1</name>
            <records>
                <record>
                    <borrowDate>2013-1-3</borrowDate>
                    <returnDate>2013-1-5</returnDate>
                </record>
                <record>
                    <borrowDate>2013-2-3</borrowDate>
                    <returnDate>2013-4-5</returnDate>
                </record>
            </records>
        </book>
        <book>
            <name>Book1</name>
            <records>
                <record>
                    <borrowDate>2013-1-3</borrowDate>
                    <returnDate>2013-1-5</returnDate>
                </record>
                <record>
                    <borrowDate>2013-2-3</borrowDate>
                    <returnDate>2013-4-5</returnDate>
                </record>
            </records>
         </book>
    </Books>
</books>

您不能使用標准序列化工具從您的問題序列化類,以便它與<bookNum>節點在同一級別上具有<book>條目。

使用標准序列化工具保存的類時, <book>節點的列表將始終嵌套到與<bookNum>節點位於同一級別的單獨陣列節點中。 同樣關注book類中的records數組字段。

要生成您想要的XML輸出 - 與<book> <bookNum>節點位於同一級別的<bookNum>節點 - 您必須在books類中實現IXmlSerializable接口以進行自定義序列化。 要查看IXmlSerializable實現的示例,請訪問以下鏈接: StackOverflow回答CodeProject文章

另一個解決方案是 - 正如所述用戶Alexandr對我的回答進行評論 - 從List<book>類型繼承您的books類,並在您的book類字段records中繼承自List<record>類型的類類型。

從您的問題序列化類時,假設您分配了正確的XmlRoot,XmlElement,XmlArray和XmlArrayItem屬性 ,如下所示:

[XmlRoot("books")]
public class books
{
    [XmlElement("bookNum")]
    public int bookNum { get; set; }

    [XmlRoot("book")]
    public class book
    {
        [XmlElement("name")]
        public string name { get; set; }

        [XmlRoot("record")]
        public class record
        {
            [XmlElement("borrowDate")]
            public string borrowDate { get; set; }

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

        [XmlArray("borrowRecords")]
        [XmlArrayItem("record")]
        public record[] records { get; set; }
    }

    [XmlArray("booksList")]
    [XmlArrayItem("book")]
    public book[] books { get; set; }
}

您將獲得如下XML輸出:

<books>
    <bookNum>2</bookNum>
    <booksList>
        <book>
            <name>Book 1</name>
            <borrowRecords>
                <record>
                    <borrowDate>2013-1-3</borrowDate>
                    <returnDate>2013-1-5</returnDate>
                </record>
                <record>            
                    <borrowDate>2013-2-3</borrowDate>
                    <returnDate>2013-4-5</returnDate>
                </record>
            </borrowRecords>
        </book>
        <book>
            <name>Book 2</name>
            <borrowRecords>
                <record>
                    <borrowDate>2013-1-3</borrowDate>
                    <returnDate>2013-1-5</returnDate>
                </record>
                <record>            
                    <borrowDate>2013-2-3</borrowDate>
                    <returnDate>2013-4-5</returnDate>
                </record>
            </borrowRecords>
        </book>
    </booksList>
</books>

我對您的類代碼進行了以下更改。 我無法使用默認的序列化程序復制XML序列化,因為它不會復制'Record'元素而不給它一個容器元素。

[System.Xml.Serialization.XmlRoot("books")]
public class books 
{
    public int bookNum { get; set; }
    public class book {
        public string name { get; set; }
        public class record {
            public string borrowDate { get; set; }
            public string returnDate { get; set; }
        }
        public record[] records { get; set; }
    }
    public book[] books { get; set; }
}

序列化這給了我以下輸出

<books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <bookNum>2</bookNum>
  <books>
    <book>
      <name>first</name>
      <records>
        <record>
          <borrowDate>19/07/2013 4:41:29 PM</borrowDate>
          <returnDate>19/07/2013 4:41:29 PM</returnDate>
        </record>
      </records>
    </book>
  </books>
</books>

使用此測試代碼

books bks = new books();
bks.bookNum = 2;
bks.books = new books.book[]{ new books.book{name="first", records = new books.book.record[] {new books.book.record{borrowDate = DateTime.Now.ToString(), returnDate = DateTime.Now.ToString()}}}};

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(books));

XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
settings.Indent = true;
settings.OmitXmlDeclaration = true;

using(StringWriter textWriter = new StringWriter()) {
    using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
        serializer.Serialize(xmlWriter, bks);
    }
    return textWriter.ToString(); //This is the output as a string
}

我意識到這已經晚了幾年,但我已經能夠通過使用XmlElementAttribute來實現你想要的結構。

我通過使用XSD.exe從xml生成模式定義並從xsd文件生成.Net代碼來發現這一點。 據我所知,這適用於.Net 3.5到4.6。

這是我使用的類定義:

public class books
{
    public int bookNum { get; set; }
    public class book {
        public string name { get; set; }
        public class record {
            public string borrowDate { get; set; }
            public string returnDate { get; set; }
        }
        [XmlElement("record")]
        public record[] records { get; set; }
    }
    [XmlElement("book")]
    public book[] allBooks { get; set; }
}

這里有一個LinqPad片段,說明序列化/反序列化(基於David Colwell的代碼片段,感謝BTW關於如何排除BOM的提示,這正是我所尋找的):

books bks = new books();
books bks2 = null;
bks.bookNum = 2;
bks.allBooks = new books.book[] 
        { 
            new books.book {
                name="book 1", 
                records = new books.book.record[] {
                        new books.book.record{borrowDate = DateTime.Now.ToString(), returnDate = DateTime.Now.ToString()}
                    }
                },
            new books.book { 
                name="book 2", 
                records = new books.book.record[] { 
                        new books.book.record{borrowDate = DateTime.Now.ToString(), returnDate = DateTime.Now.ToString()}, 
                        new books.book.record{borrowDate = DateTime.Now.ToString(), returnDate = DateTime.Now.ToString()}}
                    },
        };
string xmlString;

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(books));

XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = new UnicodeEncoding(false, false); // no BOM in a .NET string
settings.Indent = true;
settings.OmitXmlDeclaration = true;

XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
// exclude xsi and xsd namespaces by adding the following:
ns.Add(string.Empty, string.Empty);

using(StringWriter textWriter = new StringWriter()) {
    using(XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings)) {
        serializer.Serialize(xmlWriter, bks, ns);
    }
    xmlString = textWriter.ToString(); //This is the output as a string
}

xmlString.Dump();

// Deserialize the xml string now       
using ( TextReader reader = new StringReader(xmlString) ) {
    bks2 = ( books )serializer.Deserialize(reader);
}

bks2.Dump();

這樣生成的XML可以在不實現IXmlSerializable的情況下進行序列化和反序列化,例如:

<books>
  <bookNum>2</bookNum>
  <book>
    <name>book 1</name>
    <record>
      <borrowDate>2/2/2016 5:57:25 PM</borrowDate>
      <returnDate>2/2/2016 5:57:25 PM</returnDate>
    </record>
  </book>
  <book>
    <name>book 2</name>
    <record>
      <borrowDate>2/2/2016 5:57:25 PM</borrowDate>
      <returnDate>2/2/2016 5:57:25 PM</returnDate>
    </record>
    <record>
      <borrowDate>2/2/2016 5:57:25 PM</borrowDate>
      <returnDate>2/2/2016 5:57:25 PM</returnDate>
    </record>
  </book>
</books>

如果你需要其他類,比如books類中的book2,你有一些特殊的指令來實現它。

public class books
{     
   public int bookNum {get; set; }
   public class book {
         public string name {get; set; }
         public class record {
             public string borrowDate {get; set; }
             public string returnDate {get; set; }
         }
         [XmlElement ("record")]
         public record [] records {get; set; }
     }
     [XmlElement ("book")]
     public book [] allBooks {get; set; }

     public int book2Num {get; set; }
     public class book2 {
         public string name {get; set; }
         public class record {
             public string borrowDate {get; set; }
             public string returnDate {get; set; }
         }
         [XmlElement ("record")]
         public record [] records {get; set; }
     }
     [XmlElement ("book2")]
     public book2 [] allBook2 {get; set; }
}`

當我嘗試運行該程序時,我有以下錯誤:

“附加信息:反映類型時出錯”

暫無
暫無

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

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