12
votes

C # Serifisation XML, élément de collecte et racine

Mon application Serialise les objets dans les flux. Voici un échantillon de ce dont j'ai besoin: xxx

Dans ce cas, l'objet est une collection d'objet "Liens".

------------ --- La première version

Au début, j'ai utilisé le DatacontractSerializer , mais vous ne pouvez pas sérialiser les membres en tant qu'attributs ( Source )

Voici l'objet: xxx

et voici le résultat: xxx

------------ deuxième version < p> OK, pas silencieux ce que je veux, j'ai donc essayé le classique xmlsérializer , mais ... Oh nooo, vous ne pouvez pas spécifier le nom de l'élément racine et des éléments de la collection si l'élément racine est Une collection ...

Voici le code: xxx

Voici le résultat: xxx < p> ------------- Version troisième

Utilisation xmlSerializer + un élément racine: xxx

Et son résultat: xxx

sympa, mais je ne veux pas ce nœud racine !! Je veux que ma collection soit le nœud racine.

Voici les contraintes:

  • Le code de sérialisation est générique, cela fonctionne avec n'importe quoi Serializable
  • L'opération inverse (désériorialisation) doit trop travailler
  • Je ne veux pas regérogez le résultat (i Serialize directement dans un flux de sortie)

    Quelles sont mes solutions maintenant:

    1. coding mon propre xmlSerializer
    2. Trick XmlSerializer lorsqu'il fonctionne avec une collection (j'ai essayé, le devoir trouver un xmlrootelement et plurialiser pour générer son propre xmlrootatattribute, mais qui provoque un problème lors de la désérialisation + le nom d'éléments conserve toujours le nom de la classe)

      aucune idée?

      Qu'est-ce qui me dérange vraiment dans cette question, est que ce que je veux semble être vraiment vraiment simple ...


2 commentaires

Je voudrais tricher et sérialiser cela «comme il vient», puis appliquez une transformation XSL sur le XML résultant pour le masser à ce dont vous avez besoin. Alternativement, avez-vous regardé [Messagecontract]? Il offre beaucoup plus de personnalisation sur la sortie que Datacontract


La tricherie XSL n'est pas une option car le sérialisateur écrit directement dans un ruisseau ... et merci pour la tête [Messagecontract], j'ai appris quelque chose aujourd'hui ^^ Cependant, il est profondément lié à la WCF et ne permet pas de contrôler finement une simple sérialisation XML ( Je me trompe peut-être, Jsut a découvert l'attribut)


3 Réponses :


4
votes

XMLSerializer doit pouvoir faire ce dont vous avez besoin, mais il dépend fortement de la structure et de la configuration initiales. Je l'utilise dans mon propre code pour générer des choses remarquablement similaires. XXX

MAINTENANT, SERIALISANT LES LIENS La classe doit générer exactement ce que vous recherchez.

Le problème avec XMLSerializer est lorsque vous lui donnez des génériques, il répond avec des génériques. Liste des impléments de remplacement quelque part dans la présente et le résultat sérialisé sera presque toujours Arrayof . Pour contourner ce que vous pouvez nommer la propriété, ou la racine de la classe. La fermeture de ce dont vous avez besoin est probablement la deuxième version de vos exemples. Je suppose que vous avez tenté une sérialisation directe d'un list d'objet Liens. Cela ne fonctionnerait pas parce que vous n'avez pas spécifié le nœud racine. Maintenant, une approche similaire peut être trouvée ici . Dans celui-ci, ils spécifient le xmlrooTatTtribut lors de la déclaration du sérialisateur. Le vôtre ressemblerait à ceci: xxx


2 commentaires

Votre solution est très proche de la solution finale, mais je ne peux pas spécifier directement un nom d'attribut racine dans le constructeur XMLSerializer (le code de sérialisation est ailleurs), j'ai essayé de «déduire» en sérialisement, qui a fonctionné pour le nœud racine, mais pas pour les éléments. La solution a été donnée par Mike avec l'attribut «xmltype» que je ne connaissais pas.


Bits de solution combinés. Yay. Heureux d'avoir pu aider si = D



1
votes

Ici vous allez ...

 class Program
{
    static void Main(string[] args)
    {

        Links ls = new Links();
        ls.Link.Add(new Link() { Name = "Mike", Url = "www.xml.com" });
        ls.Link.Add(new Link() { Name = "Jim", Url = "www.xml.com" });
        ls.Link.Add(new Link() { Name = "Peter", Url = "www.xml.com" });

        XmlSerializer xmlSerializer = new XmlSerializer(typeof(Links));

        StringWriter stringWriter = new StringWriter();

        xmlSerializer.Serialize(stringWriter, ls);

        string serializedXML = stringWriter.ToString();

        Console.WriteLine(serializedXML);

        Console.ReadLine();
    }
}

[XmlRoot("Links")]
public class Links
{
    public Links()
    {
        Link = new List<Link>();
    }

    [XmlElement]
    public List<Link> Link { get; set; }
}

[XmlType("Link")]
public class Link
{
    [XmlAttribute("Name")]
    public string Name { get; set; }


    [XmlAttribute("Href")]
    public string Url { get; set; }

}


1 commentaires

Merci pour votre réponse. Votre solution a quelques problèmes - 1) ne fonctionne pas à cela, car les éléments ne sont pas renommés (vous avez triché, vous avez appelé le type 'link' afin que les éléments de sortie sont ) Vous pouvez contourner Ceci en spécifiant le nom de l'élément dans le nœud XMLElement ---- 2) Je préférerais éviter d'éviter une structure contenant, car elle posera un problème pour le format d'autre série (les mêmes objets sont utilisés pour plusieurs formats de sérialisation) - Cependant, vous m'avez donné une partie de la solution finale avec le XMLTypeAttribute: merci!



9
votes

OK, voici ma solution finale (espère que cela aide quelqu'un), qui peut sérialiser un tableau uni, liste , hashset , ...

Pour y parvenir, nous devrons dire au sérialisateur. Quel nœud racine à utiliser, et c'est un peu difficile ... p>

1) Utilisez 'xmltype' sur l'objet sérialisable p> xxx pré>

2) code A «Méthode« détecteur de racine intelligente », qui retournera un xmlrooTatTtribute p>

[XmlType("link")]
[XmlTypeInCollection("links")]
public class LinkFinalVersion
{
}


0 commentaires