XmlSerializer将C#对象转换为xml字符串

问题描述 投票:8回答:4

我创建了一个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>
c# xml linq
4个回答
9
投票

您不能使用标准序列化工具从您的问题序列化类,以便它将<book>条目与<bookNum>节点在同一级别上。

当使用标准序列化工具保存类时,<book>节点的列表将始终嵌套到与<bookNum>节点位于同一级别的单独阵列节点中。同样关注records类的book数组字段。

要生成您想要的XML输出 - 使用与<book>节点相同级别的<bookNum>节点 - 您必须在IXmlSerializable类中实现books接口以进行自定义序列化。要查看IXmlSerializable实现的示例,请访问以下链接:StackOverflow answerCodeProject article

另一个解决方案是 - 正如user Alexandr在评论我的回答中所述 - 从books类型继承你的List<book>类,并在你的book类字段继承records类型的List<record>类字段XmlRoot, XmlElement, XmlArray and XmlArrayItem attributes

从您的问题序列化类时,假设您分配的正确[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; } } 如下:

<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输出:

[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; }
}

8
投票

我对您的类代码进行了以下更改。我无法使用默认的序列化程序复制XML序列化,因为它不会复制'Record'元素而不给它一个容器元素。

<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

3
投票

我意识到这已经晚了几年,但我已经能够通过使用XSD.exe实现你想要的结构。

我通过使用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; } } 从xml生成模式定义并从xsd文件生成.Net代码来发现这一点。据我所知,这适用于.Net 3.5到4.6。

这是我使用的类定义:

LinqPad

这里有一个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(); 片段,说明序列化/反序列化(基于David Colwell的代码片段,感谢BTW关于如何排除BOM的提示,这正是我所寻找的):

<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>

这样生成的XML可以在不实现IXmlSerializable的情况下进行序列化和反序列化,例如:

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; }
}`

0
投票

如果你需要其他类,比如books类中的book2,你有一些特殊的指令来实现它。例

qazxswpoi

当我尝试运行该程序时,我有以下错误:

“附加信息:反映类型时出错”

© www.soinside.com 2019 - 2024. All rights reserved.