0

I have the following class fragment:

public class varString
{
    public string KeyWord;
    public string Value;
    public static implicit operator string(varString v)
    {
        return v == null ? null : (string)v.Value;
    }
}

KeyWord is allowed to be null.

When serializing to XML, I get the following output when KeyWord is null:

<varString>
    <Value>value goes here</Value>
</varString>

How can I get the XML serializer to output the following when and only when KeyWord is null?:

<varString>value goes here</varString>

If KeyWord is not null, I'd still like it to output the following:

<varString>
    <!-- Can either be <Value></Value or just straight text -->
    <KeyWord>KeyWord goes here</KeyWord>
<varString>

Please note that I have already modified the deserialize events to handle this case to convert the lone string into a varString with a null KeyWord.

Polosky
  • 88
  • 5
  • 13
  • 1
    Why do you need that? It makes the xml harder to parse for the receipent. – L.B Nov 02 '16 at 19:53
  • It's easier for me to edit the xml in this way. KeyWord is 9/10 times null, so I'd rather not have the extra tag output. Just personal preference is all, doesn't really affect anything. – Polosky Nov 02 '16 at 20:10

2 Answers2

1

Mark Value with the attribute [XmlText]:

public class varString
{
    [XmlText]
    public string Value;
    public string KeyWord;
    public static implicit operator string(varString v)
    {
        return v == null ? null : (string)v.Value;
    }
}

Sample fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • This works in the fiddle, but I can't seem to get it to work with a more complex object that contains these in my code. However, I think this is the easiest and simplest solution so I'm marking it as the answer because it does work. – Polosky Nov 02 '16 at 20:18
  • @Hondros - Check the [Remarks](https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmltextattribute.aspx#Remarks) section of the docs, e.g. *Only one instance of the XmlTextAttribute class can be applied in a class.* and *You can apply the XmlTextAttribute to public fields and public read/write properties that return primitive and enumeration types.* – dbc Nov 02 '16 at 20:20
  • 1
    Hm interesting. I modified your fiddle to see if it would support classes with defined varStrings: https://dotnetfiddle.net/yan3ts . And it does in fact work. I'm sure I can figure it out from here though. Thanks so much! – Polosky Nov 02 '16 at 20:27
  • 1
    I figured it out. I'm running a converter on some of my xml files, so the input was expecting XmlText even though tags are currently there, so they weren't being read in. – Polosky Nov 02 '16 at 20:29
0

Try this approach:

var vs = new varString();
vs.KeyWord = "key"; // null;
vs.Value = "value";


var attr = new XmlAttributes();

if (vs.KeyWord == null)
    attr.XmlText = new XmlTextAttribute();
else
    attr.XmlElements.Add(new XmlElementAttribute { ElementName = "Value" });

var overrides = new XmlAttributeOverrides();
overrides.Add(typeof(varString), "Value", attr);


var xs = new XmlSerializer(typeof(varString), overrides);
xs.Serialize(Console.Out, vs);

Depending on the KeyWord value we add XmlTextAttribute or XmlElementAttribute.

Alexander Petrov
  • 13,457
  • 2
  • 20
  • 49
  • Unfortunately, I don't think this will work for me because each varString would have a null keyword on a case by case basis, and I am using a container class to hold multiple varStrings. – Polosky Nov 02 '16 at 20:21
  • @Hondros - Yes, for multiple values it's inapplicable. – Alexander Petrov Nov 02 '16 at 20:23
  • 1
    You need to cache the serializer if you construct it using `XmlAttributeOverrides`. See [Memory Leak using StreamReader and XmlSerializer](https://stackoverflow.com/questions/23897145) – dbc Nov 02 '16 at 20:24