2

I have a node that can contain either text or xml, text + xml or text + xml + text. The first two cases i have solved using

    [XmlAnyElement]
    [EditorBrowsable(EditorBrowsableState.Never)]
    public XmlElement[] TextNodes { get; set; }

    [XmlText]
    public string InnerText { get; set; }

    [XmlIgnore]
    public string Text 
    {
        get
        {
            return String.Format("{0}{1}", InnerText, TextNodes.Aggregate(String.Empty, (current, documentNode) => current + documentNode.OuterXml));
        }
    }

However, the last case where there is text after the xml I cant find a solution for.

XML

<node>
 somtext <p>moretext</p> even more text
</node>

my code will give output in Text as:

sometext <p>moretext</p>

I need:

sometext <p>moretext</p> even more text
ruffen
  • 1,695
  • 2
  • 25
  • 51

2 Answers2

6

What you want is called mixed content and is supported in the XmlSerializer.

write your class like this

[Serializable]
public class TestClass
{
    [XmlText(typeof(string))]
    [XmlAnyElement]
    public object[] Items { get; set; }
}

and put all the elements in the same object array

Sruly
  • 10,200
  • 6
  • 34
  • 39
  • Nice! This worked like a charm. Added the ignored text property to your answer as well to make the answer complete. – ruffen Sep 24 '14 at 07:34
  • A very useful answer to find 4 years later when dealing with legacy XML APIs in the age of JSON – J.T. Taylor Nov 12 '18 at 20:38
0

you have to use CDATA - because the tags <> will break the XML-Structure use CDATA or encode your string (maybe b64)

take a look here:

how-do-you-serialize-a-string-as-cdata-using-xmlserializer

EDIT:

I think your code should look something like this after:

  [XmlIgnore]
    public string OtherXML;

    [XmlText]
    [XmlElement(ElementName = "OtherXML")]
    XmlCDataSection OtherXMLAsCdata
    {
        get
        {
            var dummy = new XmlDocument();
            return dummy.CreateCDataSection(OtherXML);
        }
        set
        {
            if (value == null)
            {
                OtherXML = null;
                return;
            }

            OtherXML = value.Value;
        }
    }
Community
  • 1
  • 1
Cadburry
  • 1,844
  • 10
  • 21
  • Assuming this involves altering the XML before serializing? (adding the cdata element) – ruffen Sep 23 '14 at 13:13
  • @ruffen take a look at the edit - your InnerText is my OtherXML – Cadburry Sep 23 '14 at 13:32
  • Tried this, but get Empty string in my unit test, does ElementName in XmlElementAttribute correspond to something that has to be present in the XML? – ruffen Sep 23 '14 at 13:38
  • ElementName defines the NodeName (ElementName) which will be generated by the xmlserializer - by default the ElementName is the PropertyName - but because of the proxy-property "OtherXMLAsCdata" i like to assign the original name of the property with the xml-string (which property is marked with the "XMLIgnore" attribute to prevent the serializer to ser. this proprtyvalue (which would brick the xml) – Cadburry Sep 23 '14 at 13:42