J'ai créé une classe 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; }
}
Mais c'est quand j'utilise XmlSerializer convertir en chaîne XML. Le résultat n'est pas le même que ci-dessous xml.
Quel est le problème de ma classe C #? Je veux utiliser XmlSerializer pour obtenir le résultat au lieu d'utiliser XmlDocument.
Des idées? Merci d'avance!
<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>
MODIFIER
Ci-dessous, mon code C # et le résultat de la sortie:
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>
Vous ne pouvez pas sérialiser la classe de votre question à l'aide des outils de sérialisation standard, de sorte qu'elle ait des entrées <book>
au même niveau que le noeud <bookNum>
.
Lorsque la classe est enregistrée avec les outils de sérialisation standard, la liste de vos nœuds <book>
sera toujours imbriquée dans un nœud array distinct qui se trouvera au même niveau que le nœud <bookNum>
. Même problème que le champ de tableau records
sur la classe book
.
Pour générer le résultat XML que vous souhaitez (avec les nœuds <book>
du même niveau que le nœud <bookNum>
), vous devez implémenter l'interface IXmlSerializable dans votre classe books
pour la sérialisation personnalisée. Pour voir des exemples d'implémentation de IXmlSerializable
, visitez ces liens: StackOverflow answer , Article de CodeProject .
Une autre solution consiste - comme indiqué utilisateur Alexandr dans le commentaire de ma réponse - à hériter de votre classe books
de type List<book>
et à avoir dans votre champ de classe book
records
un type de classe hérité du type List<record>
.
Lorsque vous sérialisez une classe à partir de votre question, en supposant que les attributs XmlRoot, XmlElement, XmlArray et XmlArrayItem appropriés sont attribués comme suit:
[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; }
}
vous obtiendrez le résultat XML comme suit:
<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>
J'ai apporté le changement suivant à votre code de classe. Je ne parviens pas à dupliquer la sérialisation XML à l'aide du sérialiseur par défaut, car celui-ci ne dupliquera pas l'élément 'Record' sans lui attribuer un élément conteneur.
[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; }
}
Sérialiser cela me donne la sortie suivante
<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>
en utilisant ce code de test
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
}
Je me rends compte que nous avons quelques années de retard, mais j’ai réussi à obtenir la structure que vous souhaitiez simplement en utilisant XmlElementAttribute .
J'ai découvert cela en utilisant XSD.exe pour générer des définitions de schéma à partir de XML et générer du code .Net à partir de fichiers xsd. Pour autant que je sache, cela fonctionne dans .Net 3.5 à 4.6.
Voici la définition de classe que j'ai utilisée:
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; }
}
Et voici un extrait de LinqPad qui illustre la sérialisation/désérialisation (basé sur l'extrait de code de David Colwell, merci BTW pour l'astuce sur la façon d'exclure une nomenclature, c'était exactement ce que je cherchais):
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();
Ce XML produit qui peut être sérialisé et désérialisé sans implémenter IXmlSerializable, tel que:
<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>
si vous avez besoin d'autres classes, telles que book2 dans la classe books, vous devez lui donner des instructions spéciales pour le mettre en œuvre.
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; }
}`
Lorsque j'essaie d'exécuter le programme, l'erreur suivante apparaît:
"Informations complémentaires: erreur lors de la représentation du type"