Search code examples
c#asp.net-corexmlserializer

XmlSerialize Class to CDATA


Due to one of the interfaces we are writing for, we have to add a CDATA tag for a list of classes.

    <modules>
        <![CDATA[<module>
            <title></title>
            <code></code>
            <level></level>
            <year></year>
            <summary></summary>
        </module>
          <module>
            <title></title>
            <code></code>
            <level></level>
            <year></year>
            <summary></summary>
        </module>]]>
    </modules>

I'm unsure how to achieve this. I have found questions around individual strings, but not so much around an entire class. Any suggestions would be helpful.


Solution

  • One of the ways to get the output you are expecting is to separate the creation of the module data and generating the CDATA part. For example:

    To create the module data -

    1. Create a class to hold module details as below -

      public class Module
      {
          public string title { get; set; }
          public string code { get; set; }
          public string level { get; set; }
          public string summary { get; set; }
       }
      
    2. Create a method to fetch these datails -

       public static string CreateXMLString()
         {
          List<Module> modules = new List<Module>();
          modules = new List<Module>() { new Module() { code = "test", 
          summary="Test3", title="Test", level = "tests1" },
                                             new Module() { code = "test3", 
          summary="Test3", title="Test3", level = "tests3" } };
      
              // Create XML to return the string in the format of 
              // <module code="test">
              //  < level > tests1 </ level >
              //  < summary > Test3 </ summary >
              //  < title > Test </ title >
              //</ module >< module code = "test3" >   
              //     < level > tests3 </ level >   
              //     < summary > Test3 </ summary >   
              //     < title > Test3 </ title >
              //   </ module >
      
            var modulesXml = 
                from mod in modules
                select new XElement("module",
              new XAttribute("code", mod.code),
              new XElement("level", mod.level),
              new XElement("summary", mod.summary),
              new XElement("title", mod.title)
             );
      
            return String.Concat(modulesXml);
          }
      

    To get the CDATA you can use the below steps -

    1. Create a class Modulesand refer the documentation for usages of CreateCDataSection and for similar threads here for the details

      [XmlType("")]
      public class Modules
      {
       public Modules() { }
      
       [XmlIgnore]
       public string Message { get; set; }
       [XmlElement("modules")]
       public System.Xml.XmlCDataSection MyStringCDATA
       {
           get
           {
              return new System.Xml.XmlDocument().CreateCDataSection(Message);
           }
           set
           {
              Message = value.Value;
           }
       }
      }
      

    To test the output assign the string generated in step 2 during serialization you can refer the sample code below

    static void Main(string[] args)
     {
       Modules mc = new Modules();
       mc.Message = CreateXMLString();//Assign your data created in step 2
       XmlSerializer serializer = new XmlSerializer(typeof(Modules));
       XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
       ns.Add("", "");
           
       StringWriter writer = new StringWriter();
    
        //Remove unnecessary namespaces
       serializer.Serialize(writer, mc,ns);
       var test = XDocument.Parse(writer.ToString());            
                
       var data = test.Root.Elements();              
                
       Console.WriteLine(data.FirstOrDefault().Value);
    
     }
    

    Output -

    <modules>
    <![CDATA[<module>
      <code>test</code>
      <level>tests1</level>
      <summary>Test3</summary>
      <title>Test</title>
    </module><module>
      <code>test3</code>
      <level>tests3</level>
      <summary>Test3</summary>
      <title>Test3</title>
    </module>]]>
    </modules>