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.)