简体   繁体   中英

XML Deserialization: Use XmlAttribute and XmlText on a single property

I am trying to deserialize a Value as either a XmlAttribute or a XmlText for equal xml tags.
When deserializing, both options should be valid and both options should end up deserializing a value into the same Property of a class.

Basically my xml looks like this:

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

And given the classes:

public class ArrayTest
{
    [XmlElement(nameof(ArrayItem))]
    public ArrayItem[] Items { get; set; }
}

public class ArrayItem
{
    //[XmlAttribute]
    //[XmlText]
    public string Value { get; set; }
}

I want "Item1" as well as "Item2" to end up in the Value property of the respective ArrayItems.

I know something like this is done in xaml for WPF, for instance when defining the Text Property of a TextBlock i am able to set it either within the xml tags as well as directly within the Text Property. Ie

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

I already tried different combinations of the corresponding class attributes, but it seems that the last one just ends up overwriting the previous one so i'm just left with one of both options.
Additionally i would prefer if this was possible using the XmlSerializer Class.

Edit: Inspired by Auditive's answer I went with this:

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

This works for my case.

Do note however, that this won't work for serialization, as that way both properties get saved.

Why do you won't use separated properties for node value and attribute value?

public class ArrayItem
{
    [XmlAttribute("Value")]
    public string ValueAttribute { get; set; }
    [XmlText]
    public string Value { get; set; }
}

With this example:

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

It will give you desired output:

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

Deserialization back from file works fine too:

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

在此处输入图片说明

I think this approach and same namings will simply misle you sooner or later.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM