CustomXmlParts.cs
- //
- // This code is part of Document Solutions for Word demos.
- // Copyright (c) MESCIUS inc. All rights reserved.
- //
- using System;
- using System.IO;
- using System.Drawing;
- using System.Collections.Generic;
- using System.Linq;
- using System.Xml;
- using GrapeCity.Documents.Word;
-
- namespace DsWordWeb.Demos
- {
- // This example demonstrates how to create a document with multiple ContentControls,
- // whose values are mapped to user-created CustomXmlPart file, standard XML file
- // which defines various elements and attributes.
- // This document also contain a header and a footer with elements that are also mapped to
- // proper xml elements.
- public class CustomXmlParts
- {
- public GcWordDocument CreateDocx()
- {
- var doc = new GcWordDocument();
-
- // Create custom xml part and keep it in the document:
- CreateOrderCustomXmlFromString(doc);
-
- // Set custom xml document element value:
- SetDeliveryOption(doc, true);
-
- // Compose document with Case properties bound to proper CustomControls:
-
- // Create and map To text field:
- CreateOficialBody(doc);
-
- // Create and map Appeal checkbox and AppealDeadline Text control:
- CreateDeliveryCheckbox(doc);
-
- // Create Header and map Department xml element:
- CreateHeaderWithMappedDepartment(doc);
-
- // Create Header and map document built-in Author xml element:
- CreateFooterWithMappedAuthor(doc);
-
- // Done:
- return doc;
- }
-
- // Retrieve a CustomXmlPart from a document by name:
- private static CustomXmlPart GetCustomXmlPartByName(GcWordDocument doc, string name)
- {
- foreach (var xmlPart in doc.CustomXmlParts)
- {
- if (string.Compare(xmlPart.XmlDocument.DocumentElement.Name, name, true) == 0)
- return xmlPart;
- }
- throw new ArgumentException(string.Format("Could not find custom xml part {0}", name));
- }
-
-
- // Find 'Order' CustomXmlPart and set its DeliveryAppeal xml element to value provided by method parameter:
- private static void SetDeliveryOption(GcWordDocument doc, bool deliveryRequired)
- {
- var xmlPart = GetCustomXmlPartByName(doc, "Order");
-
- var node = xmlPart.XmlDocument.SelectSingleNode(@"//*[local-name()='Delivery']");
- node.InnerText = deliveryRequired ? "true" : "false";
- }
-
- // Compose half of document body, map "To" text custom control to proper CustomXml field:
- private static void CreateOficialBody(GcWordDocument doc)
- {
- var p = doc.Body.Paragraphs.Add("Dear ");
- var to = p.GetRange().ContentControls.Add(ContentControlType.Text, false);
- to.XmlMapping.SetMapping(@"//mescius:To", @"xmlns:mescius='http://developer.mescius.com'");
-
- p.GetRange().Runs.First.Font.Size = 10;
- to.Font.Size = 10;
- p.GetRange().Runs.Add(",");
- doc.Body.Paragraphs.Add();
-
- p = doc.Body.Paragraphs.Add(
- "The first shipment of equipment from AMA Ltd has arrived. " +
- "We are delighted with every piece. Therefore, we decided to make " +
- "our initial purchase larger than anticipated. I am attaching our " +
- "purchase order No. 8393 for additional goods. Since you already have " +
- "a copy of our Procurement Guidelines, I shall not attach them to " +
- "this order. Current Shipping date is ");
-
- // Add shipping Date control, bound to proper section of Order CustomXmlPart:
- var dateControl = p.GetRange().ContentControls.Add(ContentControlType.Date, false);
- dateControl.DateFormat = "dd.MM.yyyy";
- //here we demonstrate how to map CustomControl with namespaces usage, it allows us write
- //clean and straight XmlPath. Its the right way of XMlMapping
- dateControl.XmlMapping.SetMapping(@"//mescius:Delivery/@DeliveryDate",
- @"xmlns:mescius='http://developer.mescius.com'");
- p.GetRange().Paragraphs.Add(
- "If you want to change it, select checkbox below and change Date, " +
- "then send this letter back to me");
- dateControl.Font.Italic = true;
-
- p.GetRange().Runs.First.Font.Size = 12;
- p.GetRange().Runs.First.Font.Italic = true;
- }
-
- // Create footer and map Author built-in property to Text content control:
- private static void CreateFooterWithMappedAuthor(GcWordDocument doc)
- {
- var footer = doc.Body.Sections.First.Footers[HeaderFooterType.Primary];
- var p = footer.Body.Paragraphs.Add("Sincerely yours, ");
-
- if (p.Document.Settings.BuiltinProperties.Author == null)
- p.Document.Settings.BuiltinProperties.Author = "Nancy Davolio";
-
- // Create Text ContentControl and bind its value to builtin Author property:
- var authorTextControl = p.GetRange().ContentControls.Add(ContentControlType.Text, false);
-
- // Use specialized SetMapping overload for document BuiltInProperties.
- // here we bind (map) ContentControl to builtin Author property:
- authorTextControl.XmlMapping.SetMapping(() => p.Document.Settings.BuiltinProperties.Author);
- }
-
- // Create header with Text ContentControl mapped to 'Department' node of 'Order' CustomXml:
- private static void CreateHeaderWithMappedDepartment(GcWordDocument doc)
- {
- // Create Header and fill it with data:
- var header = doc.Body.Sections.First.Headers[HeaderFooterType.Primary];
- var p = header.Body.Paragraphs.Add();
- var departmentTextControl = p.GetRange().ContentControls.Add(ContentControlType.Text, false);
-
- // Get our Case CustomXmlPart:
- var xmlPart = GetCustomXmlPartByName(doc, "Order");
-
- var departmentNode = xmlPart.XmlDocument.SelectSingleNode(@"//*[local-name()='Department']");
- // Mapping directly to XmlNode:
- departmentTextControl.XmlMapping.SetMapping(departmentNode);
- }
-
- // Create Delivery part, Checkbox custom control bound to Delivery node and Date custom control
- // bound to details of (possible) Delivery date.:
- private static void CreateDeliveryCheckbox(GcWordDocument doc)
- {
- var p = doc.Body.Paragraphs.Add();
-
- // Create checkbox and map it to Shipping node of 'Case' CustomXmlPart:
- var checkBox = p.GetRange().ContentControls.Add(ContentControlType.CheckBox, false);
-
- // Here we demonstrate how to map CustomControl ignoring namespaces used in the xml.
- // This way should be avoided as much as possible as pretty inefficient:
- checkBox.XmlMapping.SetMapping(@"//*[local-name()='Delivery']");
-
- p.GetRange().Runs.Add("Delivery should be done before ");
-
- // Add shipping Date control, bound to proper section of Order CustomXmlPart:
- var dateControl = p.GetRange().ContentControls.Add(ContentControlType.Date, false);
- dateControl.DateFormat = "dd.MM.yyyy";
- // Here we demonstrate how to map CustomControl with namespaces usage, it allows us write
- // clean and straight XmlPath. Its the right way of XMlMapping:
- dateControl.XmlMapping.SetMapping(@"//mescius:Delivery/@DeliveryDate",
- @"xmlns:mescius='http://developer.mescius.com'");
- }
-
- // Create XML from a string (see alternative method below):
- private static void CreateOrderCustomXmlFromString(GcWordDocument doc)
- {
- var sb = new System.Text.StringBuilder(201);
- const string ns = "'http://developer.mescius.com'";
-
- sb.AppendLine(@"<Order xmlns=" + ns + ">");
- sb.AppendLine(@" <To>Mark Donahue</To>");
- sb.AppendLine(@" <Department>Shipping department</Department>");
- sb.AppendLine(@" <Delivery DeliveryDate=""12.04.2019"">true</Delivery>");
- sb.AppendLine(@"</Order>");
-
- XmlDocument xml = new XmlDocument();
- xml.LoadXml(sb.ToString());
- CustomXmlPart xmlPart = doc.CustomXmlParts.Add(xml, Guid.NewGuid().ToString(), new string[] { ns }, "application/xml");
- }
-
- // Create XML by adding individual nodes one by one
- // (this method is not used in this sample, the previous
- // alternative is used instead):
- private static void CreateOrderCustomXml(GcWordDocument doc)
- {
- // add a custom xml part with custom settings
- const string ns = "http://developer.mescius.com";
- XmlDocument xml = new XmlDocument();
-
- xml.AppendChild(xml.CreateXmlDeclaration("1.0", "utf-8", null));
- XmlElement root = xml.CreateElement("Order", ns);
- xml.AppendChild(root);
-
- var to = root.AppendChild(xml.CreateElement("To", ns));
- to.InnerText = "Mark Donahue";
-
- var dep = root.AppendChild(xml.CreateElement("Department", ns));
- dep.InnerText = "Shipping department";
-
- XmlElement child = xml.CreateElement("Delivery", ns);
- child.InnerText = "true";
- child.SetAttribute("DeliveryDate", "12.04.2019");
-
- root.AppendChild(child);
-
- CustomXmlPart xmlPart = doc.CustomXmlParts.Add(xml, Guid.NewGuid().ToString(), new string[] { ns }, "application/xml");
-
- // Sad story: we cannot apply schemas to our custom xml parts.
- // Unlike in Office excel (where a schema can be serialized inside a document),
- // it seems that Word can work with schema URIs only so we cannot place an xsd inside the document.
- // This means that we cannot implement native xml-mapping restrictiong and verifying like
- // xmlPart.Schemas.Add(CreateCelebrationScheme());
- }
- }
- }
-