将属性序列化为元素中的 Xml 属性

Posted

技术标签:

【中文标题】将属性序列化为元素中的 Xml 属性【英文标题】:Serialize Property as Xml Attribute in Element 【发布时间】:2012-07-05 01:11:27 【问题描述】:

我有以下课程:

[Serializable]
public class SomeModel

    [XmlElement("SomeStringElementName")]
    public string SomeString  get; set; 

    [XmlElement("SomeInfoElementName")]
    public int SomeInfo  get; set; 

使用 XmlSerializer.Serialize() 进行序列化(填充一些测试数据时)会产生以下 XML:

<SomeModel>
  <SomeStringElementName>testData</SomeStringElementName>
  <SomeInfoElementName>5</SomeInfoElementName>
</SomeModel>

我需要的是:

<SomeModel>
  <SomeStringElementName Value="testData" />
  <SomeInfoElementName Value="5" />
</SomeModel>

有没有办法在不编写我自己的自定义序列化代码的情况下将其指定为属性?

【问题讨论】:

【参考方案1】:

您将需要包装类:

public class SomeIntInfo

    [XmlAttribute]
    public int Value  get; set; 


public class SomeStringInfo

    [XmlAttribute]
    public string Value  get; set; 


public class SomeModel

    [XmlElement("SomeStringElementName")]
    public SomeStringInfo SomeString  get; set; 

    [XmlElement("SomeInfoElementName")]
    public SomeIntInfo SomeInfo  get; set; 

如果您愿意,也可以使用更通用的方法:

public class SomeInfo<T>

    [XmlAttribute]
    public T Value  get; set; 


public class SomeModel

    [XmlElement("SomeStringElementName")]
    public SomeInfo<string> SomeString  get; set; 

    [XmlElement("SomeInfoElementName")]
    public SomeInfo<int> SomeInfo  get; set; 

然后:

class Program

    static void Main()
    
        var model = new SomeModel
        
            SomeString = new SomeInfo<string>  Value = "testData" ,
            SomeInfo = new SomeInfo<int>  Value = 5 
        ;
        var serializer = new XmlSerializer(model.GetType());
        serializer.Serialize(Console.Out, model);
    

将产生:

<?xml version="1.0" encoding="ibm850"?>
<SomeModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SomeStringElementName Value="testData" />
  <SomeInfoElementName Value="5" />
</SomeModel>

【讨论】:

是的,这为我提供了所需的 XML 模式,但它为模型增加了不必要的间接性和复杂性。现在,不仅仅是 Object.SomeProperty,我还有 Object.SomeProperty.Value。我意识到我可能无法同时使用内置序列化 - 但这是问题的本质。 我知道这有点老了,但我会添加从 TSomeInfo&lt;T&gt; 的隐式转换操作,反之亦然。 我们不得不以这种方式破解 XmlSerializer 来进行这样的基本处理,这很令人痛苦,但它确实给了我一个可用的选择。【参考方案2】:

有点,使用XmlAttribute 而不是XmlElement,但它看起来不像你想要的。它将如下所示:

<SomeModel SomeStringElementName="testData"> 
</SomeModel> 

我能想到的实现您想要的(本机)的唯一方法是让属性指向名为 SomeStringElementName 和 SomeInfoElementName 的对象,其中类包含一个名为“value”的 getter。您可以更进一步并使用 DataContractSerializer 以便包装类可以是私有的。 XmlSerializer 不会读取私有属性。

// TODO: make the class generic so that an int or string can be used.
[Serializable]  
public class SerializationClass

    public SerializationClass(string value)
    
        this.Value = value;
    

    [XmlAttribute("value")]
    public string Value  get; 



[Serializable]                     
public class SomeModel                     
                     
    [XmlIgnore]                     
    public string SomeString  get; set;                      

    [XmlIgnore]                      
    public int SomeInfo  get; set;   

    [XmlElement]
    public SerializationClass SomeStringElementName
    
        get  return new SerializationClass(this.SomeString); 
                   

【讨论】:

嘿,克里斯,是的,我可以使用 XmlAttribute,但正如您所说,它不能提供我需要的结果。我希望能够在不编写自己的序列化代码的情况下得到我需要的东西。 @IUnknown - 我拼凑了一种可能的方式来实现你想要的。创建类来获取节点并不漂亮,所以如果其他人知道更好的方法,我也会感兴趣。

以上是关于将属性序列化为元素中的 Xml 属性的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 XSD 中定义为属性时,自动生成的类中的字段会序列化为元素?

将 xml 数据序列化为 json 时忽略命名空间属性

如何将不同类型的子元素反序列化为基类型的列表/集合,这是相应类的属性

XML - 将属性反序列化为 Xml 子树

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性

如何序列化为包含属性的 XML?