web-dev-qa-db-ja.com

Xml属性を介してクラス名の名前を変更するにはどうすればよいですか?

SongというXMLシリアル化可能なクラスがあるとします。

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

スペースを節約するために(およびsemi-obfuscateXMLファイル)、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>

クラス/オブジェクトの名前も名前変更/再マップしたいと思います。たとえば、上記の例では、クラスの名前をSongからgに変更します。結果のXMLは次のようになります。

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

クラス名を変更することは可能ですか?via xml-attributes

DOMを手動で作成/トラバースしたくないので、デコレータを使用してDOMを実現できるかどうか疑問に思っていました。

前もって感謝します!

更新:おっと!今回は本当にやり直しました!言及するのを忘れました-私は実際にXMLでSongオブジェクトのリストをシリアライズしています。

シリアル化コードは次のとおりです。

    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()属性はリストコンテキストのオブジェクトの名前を変更しません。

何か不足していますか?

59
invarbrass

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

更新:試したところ、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>
55
Ariel Popovsky

解決策:[XmlType(TypeName = "g")]を使用します

XmlRootはXMLでのみ動作しますroot nodesドキュメント(および、名前にrootが含まれる場合は予想どおり)に基づいて!

私は仕事の他の答えを得ることができなかったので、掘り続けました...

代わりに、XmlTypeAttribute(つまり、[XmlType])とそのTypeNameプロパティはnon-rootクラス/オブジェクトに対して同様の仕事をします。

例えば.

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

これをいくつかの生産プロジェクトで使用しましたが、問題はありませんでした。

101
Gone Coding

これがドキュメントのルート要素である場合、 [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());
            }
        }
    }
}

これには、リスト自体を表すもう1つの内部要素を生成するという副作用があります。私のシステムでは、出力は次のようになります。

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

トリックを行う必要があります

0
Raj

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

動作するはずです。

0