Dynamically generate XML based on Class Properties

I recently came across a problem where I needed to dynamically generate data for a PDF file created using Adobe Livecycle Designer. Here are the main methods that I used to loop through the relevant classes and pull out the data for the file. I created a table in the DB containing a list of all the fields from the 3 main classes that need to be included in the XML data. This is done so that in the future we can add additional fields without needing to do a release to add them.

This method will return properly formed XML data that will then be attached to the PDF file. It generates the XML by looping through the PDF, Student, and Security object and retrieving the relevant data.

internal static string GetPDFDocXMLData(int pdfTemplateId, string studentId, SSO sso)
{
   var supportedFields = PDFDocData.GetListSupportedFields();
   using (var sdc = new StudentDataClient())
   using (var db = new DatabaseContainer())
   {
      var pdf = db.PDFForms.Single(f => f.Id == pdfTemplateId);
   
      FillSupportedFields("PDFTemplate", pdf, typeof(PDFForm), supportedFields);
      if (studentId != string.Empty)
      {
         var student = sdc.GetStudentInfo(Int32.Parse(studentId));
         FillSupportedFields("StudentInfo", student, typeof(StudentInfo), supportedFields);
      }
      FillSupportedFields("SSO", sso, typeof(SSO), supportedFields);
      return CreateXML(supportedFields);
   }
}

This method loops through all the properties in the indicated class object and loads any that match the list of valid supported fields. It adds the value of the field to the PDFDocData item.

private static void FillSupportedFields(string cName, object obj, IReflect type, IEnumerable<pdfdocdata> supportedFields)
{
   var props = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);

   foreach (var item in supportedFields.Where(sf => sf.ClassName == cName))
   {
      foreach (var propInfo in props.Where(f => f.Name == item.FieldName).ToList())
      {
         item.Value = propInfo.GetValue(obj, null).ToString();
      }
   }
}

This method generates the properly formed XML string that will be used.

private static string CreateXML(IEnumerable<pdfdocdata> supportedFields)
{
   var doc = new XmlDocument();

   var dec = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
   doc.AppendChild(dec);

   var root = doc.CreateElement("form1");
   doc.AppendChild(root);

   foreach (var item in supportedFields)
   {
      var element = doc.CreateElement(item.ClassName + item.FieldName);
      element.InnerText = item.Value;
      root.AppendChild(element);
   }
   return doc.OuterXml;
}

This class looks at the DataBase and pulls the list of supported fields and populates a list containing all the information about the fields except for the value which is populated in the FillSupportedFields method.

public class PDFDocData
{
   public string ClassName { get; set; }
   public string FieldName { get; set; }
   public string Description { get; set; }
   public string Value { get; set; }
   public static List<pdfdocdata> GetListSupportedFields()
   {
      using (var db = new DatabaseContainer())
      {
         return db.PDFSupportedFields.Select(s => new PDFDocData()
                                             {
                                                ClassName = s.ClassName,
                                                FieldName = s.FieldName,
                                                Description = s.Description
                                             }).ToList();
      }
   }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s