XML 反序列化:在单个属性上使用 XmlAttribute 和 XmlText

Posted

技术标签:

【中文标题】XML 反序列化:在单个属性上使用 XmlAttribute 和 XmlText【英文标题】:XML Deserialization: Use XmlAttribute and XmlText on a single property 【发布时间】:2021-12-01 00:08:21 【问题描述】:

我正在尝试将值反序列化为 XmlAttributeXmlText 以获取相同的 xml 标签。 反序列化时,两个选项都应该有效,并且两个选项最终都应该将一个值反序列化为一个类的相同属性。

基本上我的 xml 看起来像这样:

<ArrayTest>
  <ArrayItem>Item1</ArrayItem>
  <ArrayItem Value="Item2"/>
</ArrayTest>

并给出类:

public class ArrayTest

    [XmlElement(nameof(ArrayItem))]
    public ArrayItem[] Items  get; set; 


public class ArrayItem

    //[XmlAttribute]
    //[XmlText]
    public string Value  get; set; 

我希望“Item1”和“Item2”最终出现在各自 ArrayItems 的 Value 属性中。

我知道这样的事情是在用于 WPF 的 xaml 中完成的,例如,在定义 TextBlock 的 Text 属性时,我可以在 xml 标记内以及直接在 Text 属性内进行设置。即

<TextBlock Text="Sample text"/>
<TextBlock>
    Sample Text
<TextBlock/>

我已经尝试了相应类属性的不同组合,但似乎最后一个最终覆盖了前一个,所以我只剩下两个选项之一。 此外,如果可以使用XmlSerializer 类,我更愿意这样做。

编辑:Auditive 的 回答的启发,我选择了这个:

public class ArrayItem

    [XmlAttribute(nameof(Value))]
    public string ValueAttribute
    
        get => mValue;
        set => mValue = value;
    

    [XmlText]
    public string Value
    
        get => mValue;
        set => mValue = value;
    
    
    private string mValue;

这适用于我的情况。

但请注意,这不适用于序列化,因为这样会保存两个属性。

【问题讨论】:

【参考方案1】:

为什么不将节点值和属性值分开使用?

public class ArrayItem

    [XmlAttribute("Value")]
    public string ValueAttribute  get; set; 
    [XmlText]
    public string Value  get; set; 

用这个例子:

static void Main(string[] args)

    ArrayTest arrayTest = new ArrayTest
    
        Items = new ArrayItem[] 
        
            new ArrayItem Value = "Item1" ,
            new ArrayItem ValueAttribute = "Item2" 
        
    ;

    XmlSerializer serializer = new XmlSerializer(typeof(ArrayTest));
    using FileStream fs = new FileStream("MyFile.xml", FileMode.OpenOrCreate);
        serializer.Serialize(fs, arrayTest);

它会给你想要的输出:

<?xml version="1.0"?>
<ArrayTest>
    <ArrayItem>Item1</ArrayItem>
    <ArrayItem Value="Item2" />
</ArrayTest>

从文件反序列化也可以正常工作:

using (FileStream fs = new FileStream("H:\\MyFile2.xml", FileMode.OpenOrCreate))

    ArrayTest deserializedArrayTest = formatter.Deserialize(fs) as ArrayTest;

    foreach (ArrayItem arrayItem in deserializedArrayTest.Items)
        Console.WriteLine("Array item value: " + arrayItem.Value + "\n" +
                          "Array \"Value\" attribute value: " + arrayItem.ValueAttribute);

我认为这种方法和相同的命名迟早会误导你。

【讨论】:

我的要求是该值应该可以由单个属性访问。但是你给了我一个想法。根据您的 2 个属性,我可以实现一个私有字段,这两个属性都指向。

以上是关于XML 反序列化:在单个属性上使用 XmlAttribute 和 XmlText的主要内容,如果未能解决你的问题,请参考以下文章

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

如何在将 xml 反序列化为 c# 对象时获取单个 xml 元素的多个值?

使用属性和未包装的集合反序列化 XML 响应

Json.NET - CustomCreationConverter 中单个属性的默认反序列化行为

反序列化带有属性的 XML 数组

如何反序列化 C# 中只有属性的 xml 元素?