Подтвердить что ты не робот

Как переименовать имена классов с помощью атрибутов Xml?

Предположим, что у меня есть XML-сериализуемый класс Песня:

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

Чтобы сэкономить место (а также полу-обфускать XML файл), я решил переименовать элементы xml:

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

Это приведет к созданию XML-вывода следующим образом:

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

Я хочу переименовать/переназначить имя класса/объекта. Скажем, в приведенном выше примере я хочу переименовать класс Песня в g. Чтобы получившийся xml выглядел так:

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

Можно ли переименовать имена классов через xml-attributes?

Я не хочу создавать/перемещать DOM вручную, поэтому мне было интересно, можно ли это сделать через декоратор.

Спасибо заранее!

ОБНОВЛЕНИЕ: Упс! На этот раз я действительно сделал это снова! Забыл упомянуть - я фактически сериализую список объектов Song в XML.

Здесь код сериализации:

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

И вот вывод 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>

По-видимому, атрибут XmlRoot() не переименовывает объект в контексте списка.

Я что-то пропустил?

4b9b3361

Ответ 1

Оформить атрибут XmlRoot.

Документацию можно найти здесь: 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

UPDATE: Просто попробовал, и он отлично работает на VS 2008. Этот код:

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

Выходы:

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

Ответ 2

Решение. Используйте [XmlType (TypeName = "g" )]

XmlRoot работает только с корневыми узлами XML в соответствии с документацией (и то, что вы ожидаете, учитывая, что его имя включает в себя root)!

Мне не удалось получить какие-либо другие ответы на работу, чтобы они продолжали копаться...

Вместо этого я обнаружил, что XmlTypeAttribute (т.е. [XmlType]) и его свойство TypeName выполняют аналогичное задание для не-корневых классов/объектов.

например.

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

Предполагая, что вы примените его к другим классам, например:

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

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

Это приведет к тому, что в вопросе будет указано следующее:

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

Я использовал это в нескольких производственных проектах и ​​не нашел с ним никаких проблем.

Ответ 3

Если это корневой элемент документа, вы можете использовать [XmlRoot ( "g" )].


Вот мой обновленный ответ, основанный на ваших разъяснениях. Степень контроля, о которой вы просите, невозможна без класса упаковки. В этом примере используется класс SongGroup для переноса списка, чтобы вы могли давать альтернативные имена элементам внутри.

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());
            }
        }
    }
}

Это имеет побочный эффект создания еще одного внутреннего элемента, представляющего сам список. В моей системе вывод выглядит следующим образом:

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

Ответ 4

[XmlRoot("g")]
class Song
{
}

Должен сделать трюк