如何通过Xml属性重命名类名?

时间:2021-12-18 07:18:33

Suppose I have an XML-serializable class called Song:

假设我有一个名为Song的XML-serializable类:

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

In order to save space (and also semi-obfuscate the XML file), I decide to rename the xml elements:

为了节省空间(并且半模糊XML文件),我决定重命名XML元素:

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

This will produce XML output like this:

这将产生如下XML输出:

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

I want to rename/remap the name of the class/object as well. Say, in the above example, I wish to rename the class Song to g. So that the resultant xml should look like this:

我还想重命名/重映射类/对象的名称。例如,在上面的示例中,我希望将类Song重命名为g。

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

Is it possible to rename class-names via xml-attributes?

是否可以通过xml属性重命名类名?

I don't wish to create/traverse the DOM manually, so I was wondering if it could be achieved via a decorator.

我不希望手工创建/遍历DOM,所以我想知道是否可以通过decorator实现。

Thanks in advance!

提前谢谢!

UPDATE: Oops! This time I really did it again! Forgot to mention - I'm actually serializing a list of Song objects in the XML.

更新:哎呀!这次我真的又做了!忘了说——我实际上是在序列化XML中的歌曲对象列表。

Here's the serialization code:

序列化代码:

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

And here's the XML output:

这里是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>

Apparently, the XmlRoot() attribute doesn't rename the object in a list context.

显然,XmlRoot()属性不会在列表上下文中重命名对象。

Am I missing something?

我遗漏了什么东西?

5 个解决方案

#1


40  

Checkout the XmlRoot attribute.

结帐XmlRoot属性。

Documentation can be found here: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute(v=VS.90).aspx

文档可以在这里找到:http://msdn.microsoft.com/en- us/library/system.xml.serializ.xmlrootattribute (v=VS.90).aspx

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

UPDATE: Just tried and it works perfectly on VS 2008. This code:

更新:刚刚试过,在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; }
} 

Outputs:

输出:

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


82  

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

XmlRoot only works with XML root nodes as per the documentation (and what you would expect, given its name includes root)!

XmlRoot只与XML根节点一起工作,根据文档(以及您所期望的,给定它的名称包括根)!

I was unable to get any of the other answers to work so kept digging...

我找不到工作的其他答案,所以继续挖掘……

Instead I found that the XmlTypeAttribute (i.e. [XmlType]) and its TypeName property do a similar job for non-root classes/objects.

相反,我发现XmlType属性(即[XmlType])及其TypeName属性对非根类/对象执行类似的工作。

e.g.

如。

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

Assuming you apply it to the other classes e.g.:

假设你把它应用到其他的课上。

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

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

This will output the following exactly as required in the question:

这将准确地输出以下内容:

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

I have used this in several production projects and found no problems with it.

我已经在几个生产项目中使用过它,并且没有发现任何问题。

#3


5  

If this is the root element of the document, you can use [XmlRoot("g")].

如果这是文档的根元素,您可以使用[XmlRoot("g")]。


Here is my updated response based on your clarification. The degree of control you are asking for is not possible without a wrapping class. This example uses a SongGroup class to wrap the list so that you can give alternate names to the items within.

以下是我根据你的澄清更新后的回复。没有包装类,您所要求的控制程度是不可能的。这个示例使用一个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());
            }
        }
    }
}

This has the side effect of generating one more inner element representing the list itself. On my system, the output looks like this:

这样做的副作用是生成一个表示列表本身的内部元素。在我的系统中,输出是这样的:

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


0  

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

Should do the trick

应该足够了

#5


0  

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

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

should work.

应该工作。

#1


40  

Checkout the XmlRoot attribute.

结帐XmlRoot属性。

Documentation can be found here: http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlrootattribute(v=VS.90).aspx

文档可以在这里找到:http://msdn.microsoft.com/en- us/library/system.xml.serializ.xmlrootattribute (v=VS.90).aspx

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

UPDATE: Just tried and it works perfectly on VS 2008. This code:

更新:刚刚试过,在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; }
} 

Outputs:

输出:

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


82  

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

XmlRoot only works with XML root nodes as per the documentation (and what you would expect, given its name includes root)!

XmlRoot只与XML根节点一起工作,根据文档(以及您所期望的,给定它的名称包括根)!

I was unable to get any of the other answers to work so kept digging...

我找不到工作的其他答案,所以继续挖掘……

Instead I found that the XmlTypeAttribute (i.e. [XmlType]) and its TypeName property do a similar job for non-root classes/objects.

相反,我发现XmlType属性(即[XmlType])及其TypeName属性对非根类/对象执行类似的工作。

e.g.

如。

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

Assuming you apply it to the other classes e.g.:

假设你把它应用到其他的课上。

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

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

This will output the following exactly as required in the question:

这将准确地输出以下内容:

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

I have used this in several production projects and found no problems with it.

我已经在几个生产项目中使用过它,并且没有发现任何问题。

#3


5  

If this is the root element of the document, you can use [XmlRoot("g")].

如果这是文档的根元素,您可以使用[XmlRoot("g")]。


Here is my updated response based on your clarification. The degree of control you are asking for is not possible without a wrapping class. This example uses a SongGroup class to wrap the list so that you can give alternate names to the items within.

以下是我根据你的澄清更新后的回复。没有包装类,您所要求的控制程度是不可能的。这个示例使用一个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());
            }
        }
    }
}

This has the side effect of generating one more inner element representing the list itself. On my system, the output looks like this:

这样做的副作用是生成一个表示列表本身的内部元素。在我的系统中,输出是这样的:

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


0  

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

Should do the trick

应该足够了

#5


0  

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

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

should work.

应该工作。