web-dev-qa-db-fra.com

Comment puis-je renommer des noms de classe via des attributs Xml?

Supposons que j'ai une classe XML sérialisable appelée Song:

[Serializable]
class Song
{
    public string Artist;
    public string SongTitle;
}

Afin d'économiser de l'espace (et aussi semi-obscurcir le fichier XML), je décide de renommer les éléments xml:

[XmlRoot("g")]
class Song
{
    [XmlElement("a")]
    public string Artist;
    [XmlElement("s")]
    public string SongTitle;
}

Cela produira une sortie XML comme ceci:

<Song>
  <a>Britney Spears</a>
  <s>I Did It Again</s>
</Song>

Je veux également renommer/remapper le nom de la classe/de l'objet. Disons que dans l'exemple ci-dessus, je souhaite renommer la classe Song en g. Pour que le xml résultant ressemble à ceci:

<g>
  <a>Britney Spears</a>
  <s>I Did It Again</s>
</g>

Est-il possible de renommer les noms de classe via xml-attributes?

Je ne souhaite pas créer/parcourir le DOM manuellement, donc je me demandais si cela pouvait être réalisé via un décorateur.

Merci d'avance!

MISE À JOUR: Oups! Cette fois, je vraiment l'ai encore fait! J'ai oublié de mentionner - je sérialise en fait une liste d'objets Song dans le XML.

Voici le code de sérialisation:

    public static bool SaveSongs(List<Song> songs)
    {
            XmlSerializer serializer = new XmlSerializer(typeof(List<Song>));
            using (TextWriter textWriter = new StreamWriter("filename"))
            {
                serializer.Serialize(textWriter, songs);
            }
    }

Et voici la sortie XML:

<?xml version="1.0" encoding="utf-8"?>
<ArrayOfSong>
<Song>
  <a>Britney Spears</a>
  <s>Oops! I Did It Again</s>
</Song>
<Song>
  <a>Rihanna</a>
  <s>A Girl Like Me</s>
</Song>
</ArrayOfSong>

Apparemment, l'attribut XmlRoot () ne renomme pas l'objet dans un contexte de liste.

Suis-je en train de manquer quelque chose?

59
invarbrass

Extraire l'attribut XmlRoot.

La documentation peut être trouvée ici: http://msdn.Microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute (v = VS.90) .aspx

[XmlRoot(Namespace = "www.contoso.com", 
     ElementName = "MyGroupName", 
     DataType = "string", 
     IsNullable=true)]
public class Group

MISE À JOUR: Je viens d'essayer et cela fonctionne parfaitement sur VS 2008. Ce code:

[XmlRoot(ElementName = "sgr")]
public class SongGroup
{
    public SongGroup()
    {
       this.Songs = new List<Song>();
    }



[XmlElement(ElementName = "sgs")]
    public List<Song> Songs { get; set; }
}

[XmlRoot(ElementName = "g")]
public class Song
{
    [XmlElement("a")]
    public string Artist { get; set; }

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

Les sorties:

<?xml version="1.0" encoding="utf-8"?>
<sgr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www
.w3.org/2001/XMLSchema">
  <sgs>
    <a>A1</a>
    <s>S1</s>
  </sgs>
  <sgs>
    <a>A2</a>
    <s>S2</s>
  </sgs>
</sgr>
55
Ariel Popovsky

Solution: utilisez [XmlType (TypeName = "g")]

XmlRoot ne fonctionne qu'avec les nœuds racine XML selon la documentation (et ce que vous attendez, étant donné que son nom inclut racine )!

Je n'ai pu obtenir aucune des autres réponses au travail, alors j'ai continué à creuser ...

Au lieu de cela, j'ai trouvé que le XmlTypeAttribute (c'est-à-dire [XmlType]) et sa propriété TypeName font un travail similaire pour non root classes/objets.

par exemple.

[XmlType(TypeName="g")]
class Song
{
    public string Artist;
    public string SongTitle;
}

En supposant que vous l'appliquez aux autres classes, par exemple:

[XmlType(TypeName="a")]
class Artist
{
    .....
}

[XmlType(TypeName="s")]
class SongTitle
{
    .....
}

Cela produira les éléments suivants exactement comme requis dans la question :

<g>
  <a>Britney Spears</a>
  <s>I Did It Again</s>
</g>

Je l'ai utilisé dans plusieurs projets de production et je n'ai trouvé aucun problème avec cela.

101
Gone Coding

S'il s'agit de l'élément racine du document, vous pouvez utiliser [XmlRoot ("g")] .


Voici ma réponse mise à jour sur la base de votre clarification. Le degré de contrôle que vous demandez n'est pas possible sans une classe d'emballage. Cet exemple utilise une classe SongGroup pour encapsuler la liste afin que vous puissiez donner des noms alternatifs aux éléments qu'il contient.

using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

public class SongGroup
{
    public SongGroup()
    {
        this.Songs = new List<Song>();
    }

    [XmlArrayItem("g", typeof(Song))]
    public List<Song> Songs { get; set; }
}

public class Song 
{ 
    public Song()
    {
    }

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

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

internal class Test
{
    private static void Main()
    {
        XmlSerializer serializer = new XmlSerializer(typeof(SongGroup));

        SongGroup group = new SongGroup();
        group.Songs.Add(new Song() { Artist = "A1", SongTitle = "S1" });
        group.Songs.Add(new Song() { Artist = "A2", SongTitle = "S2" });

        using (Stream stream = new MemoryStream())
        using (StreamWriter writer = new StreamWriter(stream))
        {
            serializer.Serialize(writer, group);
            stream.Seek(0, SeekOrigin.Begin);
            using (StreamReader reader = new StreamReader(stream))
            {
                Console.WriteLine(reader.ReadToEnd());
            }
        }
    }
}

Cela a pour effet secondaire de générer un élément interne de plus représentant la liste elle-même. Sur mon système, la sortie ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?>
<SongGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Songs>
    <g>
      <a>A1</a>
      <s>S1</s>
    </g>
    <g>
      <a>A2</a>
      <s>S2</s>
    </g>
  </Songs>
</SongGroup>
5
bobbymcr
[XmlRoot("g")]
class Song
{
}

Devrait faire l'affaire

0
Raj

Utilisez XmlElementAttribute: http://msdn.Microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute.aspx

[Serializable]
[XmlRoot(ElementName="g")]
class Song
{
    public string Artist;
    public string SongTitle;
}

devrait marcher.

0
Andreas Paulsson