3

I have seen the solution to get XmlSerializer to output a CDATA section, but is it then possible to conditionally achieve this, based on another value?

The following code demonstrates the result I want:

enum LogItemType
{
   Default,
   Xml
}

class LogItem
{
   public string Name { get; set; }
   public LogItemType Type { get; set; }
   [XmlIgnore]
   public string Value { get; set; }
   public XmlCDataSection ValueString
   {
      if(Type == LogItemType.Xml)
         // return CDATA
      else
         // return string (not CDATA)
   }
}
Community
  • 1
  • 1
Aaron Anodide
  • 16,906
  • 15
  • 62
  • 121

1 Answers1

3

Change the return type of your ValueString property to XmlCharacterData, which is the base class for XmlText and XmlCDataSection. Then return one or the other depending on the state of your Type property:

public class LogItem
{
    public string Name { get; set; }
    public LogItemType Type { get; set; }

    [XmlIgnore]
    public string Value { get; set; }

    [XmlElement("Value")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public XmlCharacterData ValueString
    {
        get
        {
            if (Value == null)
                return null;
            else if (Type == LogItemType.Xml)
                // return CDATA
                return new XmlDocument().CreateCDataSection(Value);
            else
                // return string (not CDATA)
                return new XmlDocument().CreateTextNode(Value);
        }
        set
        {
            Value = value == null ? null : value.Value;
        }
    }
}

The output will be either:

<LogItem>
    <Name>test</Name>
    <Type>Default</Type>
    <Value>this is a test string</Value>
</LogItem>

or

<LogItem>
    <Name>test</Name>
    <Type>Xml</Type>
    <Value><![CDATA[this is a test string]]></Value>
</LogItem>

Alternatively, if you want your Value text to be the value of the LogItem itself (rather than the value of a nested element) you can do:

    [XmlText]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public XmlNode [] ValueString
    {
        get
        {
            if (Value == null)
                return null;
            else if (Type == LogItemType.Xml)
                // return CDATA
                return new XmlNode[] { new XmlDocument().CreateCDataSection(Value) };
            else
                // return string (not CDATA)
                return new XmlNode[] { new XmlDocument().CreateTextNode(Value) };
        }
        set
        {
            Value = value == null ? null : string.Concat(value.Select(n => n.Value).ToArray());
        }
    }

(Note that an array is returned not a single item. XmlSerializer seems to require this.)

dbc
  • 104,963
  • 20
  • 228
  • 340