14
public class Hat
{
    [XmlTextAttribute]
    public string Name { get; set; }
    [XmlAttribute("Color")]
    public string Color { get; set; }
}

var hat1 = new Hat {Name="Cool Hat", Color="Red"};
var hat2 = new Hat {Name="Funky Hat", Color=null};

This is what I get (notice missing color-attribute on Funky Hat):

<Hats>
 <Hat Color="Red">Cool Hat</Hat>
 <Hat>Funky Hat</Hat>
</Hats>

This is what I want:

<Hats>
 <Hat Color="Red">Cool Hat</Hat>
 <Hat Color="">Funky Hat</Hat>
</Hats>

How can I force the serializer to create an empty attribute in stead of leaving it out?

EDIT:

Turns out I am an idiot and created an example that contained an error, because I wanted to simplify the code for the example.

If the value of color is "" (or string.empty), it is actually serialized as an empty attribute. However, I really had a null value, not an empty string - hence it was left out.

So the behavior I wanted was actually already the behavior of the example I created.

Sorry, guys!

1
  • "If the value of color is "" (or string.empty), it is actually serialized as an empty attribute. However, I really had a null value, not an empty string - hence it was left out." Wow didn't notice that behavior before. Interesting point. Commented Apr 29, 2011 at 17:45

3 Answers 3

7

Try using List<Hat> as the container. Using this:

var hats = new List<Hat>
    {
        new Hat { Name = "Cool Hat", Color = "Red" }, 
        new Hat { Name = "Funky Hat", Color = string.Empty }
    };

using (var stream = new FileStream("test.txt", FileMode.Truncate))
{
    var serializer = new XmlSerializer(typeof(List<Hat>));
    serializer.Serialize(stream, hats);
}

I get this:

<?xml version="1.0"?>
<ArrayOfHat xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Hat Color="Red">Cool Hat</Hat>
  <Hat Color="">Funky Hat</Hat>
</ArrayOfHat>
Sign up to request clarification or add additional context in comments.

1 Comment

This put me on the right track, as my container was already a List<Hat>.
1

You could try setting the Specified property to true. Also, I believe you can use a ##Specified property to control serialization, like this:

[XmlAttribute("Color")]
public string Color { get; set; }
[XmlIgnore]
public bool ColorSpecified { get { return true; } }    // will always serialize

Or you can serialize as long as it is not null:

[XmlIgnore]
public bool ColorSpecified { get { return this.Color != null; } }

2 Comments

This does not seem to work. Nothing changes in the serialized XML. Just to be clear - it is supposed to work simply because the serializer looks for a bool property named [property]Specified - in this case ColorSpecified?
@Kjensen: I know it works for elements (and the [property]Specified is something built-in and hard-coded into the serializer - see msdn.microsoft.com/en-us/library/bb402199(v=exchg.140).aspx). The same may not work for attributes.
1

There are two ways you can do this.

You could use [XmlElement(IsNullable=true)], which will force the null value to be recognized.

You could also use String.Empty instead of "". This is recognized as an empty string and not a null.

2 Comments

[XmlElement(Isnullable=true)] only works on elements, not attributes.
Try it. It has been a while, but I remember it worked for me before. There is small difference between String.Empty and "". The former does not actually create an object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.