diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data.sln b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data.sln
new file mode 100644
index 000000000..2184ee2fe
--- /dev/null
+++ b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35527.113 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MailMerge-XML-with-HTML-data", "MailMerge-XML-with-HTML-data\MailMerge-XML-with-HTML-data.csproj", "{5B0540C8-1A4D-4BB4-A0B9-10028D140E00}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5B0540C8-1A4D-4BB4-A0B9-10028D140E00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5B0540C8-1A4D-4BB4-A0B9-10028D140E00}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5B0540C8-1A4D-4BB4-A0B9-10028D140E00}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5B0540C8-1A4D-4BB4-A0B9-10028D140E00}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Data.xml b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Data.xml
new file mode 100644
index 000000000..1eb899821
--- /dev/null
+++ b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Data.xml
@@ -0,0 +1,12 @@
+
+
+
+ Login
+ This component handles <strong> user authentication <strong>
+
+
+ Dashboard
+ The dashboard <em>summarizes<em> key metrics
+
+
+
diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Template.docx b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Template.docx
new file mode 100644
index 000000000..8c9f91955
Binary files /dev/null and b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Data/Template.docx differ
diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/MailMerge-XML-with-HTML-data.csproj b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/MailMerge-XML-with-HTML-data.csproj
new file mode 100644
index 000000000..8d8c2df15
--- /dev/null
+++ b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/MailMerge-XML-with-HTML-data.csproj
@@ -0,0 +1,27 @@
+
+
+
+ Exe
+ net8.0
+ MailMerge_XML_with_HTML_data
+ enable
+ enable
+
+
+
+
+
+
+
+
+ Always
+
+
+ Always
+
+
+ Always
+
+
+
+
diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Output/.gitkeep b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Output/.gitkeep
new file mode 100644
index 000000000..5f282702b
--- /dev/null
+++ b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Output/.gitkeep
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Program.cs b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Program.cs
new file mode 100644
index 000000000..45938c4ed
--- /dev/null
+++ b/Mail-Merge/MailMerge-XML-with-HTML-data/.NET/MailMerge-XML-with-HTML-data/Program.cs
@@ -0,0 +1,155 @@
+using Syncfusion.DocIO;
+using Syncfusion.DocIO.DLS;
+using System.Dynamic;
+using System.Xml;
+
+
+// Dictionary to temporarily hold merge field HTML values and their positions.
+Dictionary> paraToInsertHTML = new Dictionary>();
+
+// Load the Word document template
+using (WordDocument document = new WordDocument(Path.GetFullPath(@"Data/Template.docx")))
+{
+ // Load the XML file that contains data to be merged
+ Stream xmlStream = System.IO.File.OpenRead(Path.GetFullPath(@"Data/Data.xml"));
+ XmlDocument xmlDocument = new XmlDocument();
+ xmlDocument.Load(xmlStream);
+ xmlStream.Dispose(); // Close and release the file stream
+
+ // Convert the XML data into a dynamic ExpandoObject structure
+ ExpandoObject allDataObject = new ExpandoObject();
+ GetDataAsExpandoObject(xmlDocument.LastChild, ref allDataObject);
+
+ // Traverse the dynamic data to extract and map mail merge records
+ if (allDataObject is IDictionary allObjects &&
+ allObjects.ContainsKey("Root"))
+ {
+ var rootObjects = (allObjects["Root"] as List)[0] as IDictionary;
+ if (rootObjects.ContainsKey("Validator"))
+ {
+ var validatorObjects = (rootObjects["Validator"] as List)[0] as IDictionary;
+
+ // Iterate over each component inside Validator (e.g., Login, Dashboard)
+ foreach (var validatorObject in validatorObjects)
+ {
+ var componentMainTag = validatorObject.Key; // Typically "Component"
+ var componentData = validatorObject.Value as List;
+
+ if (componentData != null)
+ {
+ // Create a mail merge data table for each component
+ MailMergeDataTable componentDataTable = new MailMergeDataTable(componentMainTag, componentData);
+
+ // Attach event handler to handle HTML merge fields
+ document.MailMerge.MergeField += new MergeFieldEventHandler(MergeFieldEvent);
+
+ // Execute group mail merge using nested data table
+ document.MailMerge.ExecuteGroup(componentDataTable);
+ }
+ }
+ }
+ }
+
+ // After mail merge is complete, insert HTML into placeholders
+ InsertHtml();
+
+ // Detach mail merge event handlers
+ document.MailMerge.MergeField -= new MergeFieldEventHandler(MergeFieldEvent);
+
+ // Save the updated document
+ document.Save(Path.GetFullPath(@"Output/Result.docx"), FormatType.Docx);
+}
+
+///
+/// Event handler that intercepts the mail merge process to handle HTML content.
+///
+void MergeFieldEvent(object sender, MergeFieldEventArgs args)
+{
+ if (args.FieldName.Equals("Description"))
+ {
+ // Get the paragraph containing the current merge field
+ WParagraph paragraph = args.CurrentMergeField.OwnerParagraph;
+
+ // Get the index of the merge field inside the paragraph
+ int mergeFieldIndex = paragraph.ChildEntities.IndexOf(args.CurrentMergeField);
+
+ // Store the HTML field value with its position
+ Dictionary fieldValues = new Dictionary();
+ fieldValues.Add(mergeFieldIndex, args.FieldValue.ToString());
+
+ // Associate the paragraph with its corresponding HTML values
+ paraToInsertHTML.Add(paragraph, fieldValues);
+
+ // Remove the default text replacement; HTML will be inserted later
+ args.Text = string.Empty;
+ }
+}
+
+///
+/// Recursively parses XML nodes into ExpandoObject structure for easy access.
+/// Supports handling of HTML content inside text nodes.
+///
+void GetDataAsExpandoObject(XmlNode node, ref ExpandoObject dynamicObject)
+{
+ try
+ {
+ // Check if node is simple text (possibly with HTML tags)
+ if (node.InnerText == node.InnerXml || (node.ChildNodes.Count == 1 && node.FirstChild.NodeType == XmlNodeType.Text))
+ {
+ if (!(dynamicObject as IDictionary).ContainsKey(node.LocalName))
+ (dynamicObject as IDictionary).Add(node.LocalName, node.InnerText);
+ }
+ else
+ {
+ List childObjects;
+
+ // Reuse existing list if it already exists for this node
+ if ((dynamicObject as IDictionary).ContainsKey(node.LocalName))
+ childObjects = (dynamicObject as IDictionary)[node.LocalName] as List;
+ else
+ {
+ childObjects = new List();
+ (dynamicObject as IDictionary).Add(node.LocalName, childObjects);
+ }
+
+ ExpandoObject childObject = new ExpandoObject();
+
+ // Recursively parse each child node
+ foreach (XmlNode childNode in node.ChildNodes)
+ {
+ GetDataAsExpandoObject(childNode, ref childObject);
+ }
+
+ childObjects.Add(childObject);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error in XML reading: " + e.ToString());
+ }
+}
+
+///
+/// Replaces merge fields with actual HTML content using collected placeholders.
+///
+void InsertHtml()
+{
+ // Iterate each paragraph and its associated HTML values
+ foreach (KeyValuePair> dictionaryItems in paraToInsertHTML)
+ {
+ WParagraph paragraph = dictionaryItems.Key;
+ Dictionary values = dictionaryItems.Value;
+
+ foreach (KeyValuePair valuePair in values)
+ {
+ int index = valuePair.Key;
+ string fieldValue = valuePair.Value;
+
+ // Insert HTML at the specified location in the paragraph
+ paragraph.OwnerTextBody.InsertXHTML(fieldValue, paragraph.OwnerTextBody.ChildEntities.IndexOf(paragraph), index);
+ }
+ }
+
+ // Clear dictionary after inserting all HTML
+ paraToInsertHTML.Clear();
+}