From 44ec9daab922df9058b11c1cdb980f6f773c55b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?I=C3=B1aki=20Elcoro-Iribe?= <ielcoro@asemblia.com>
Date: Fri, 27 Mar 2020 12:10:34 +0100
Subject: [PATCH] Add support for OPTIONAL in Table and Conditional

---
 OpenXmlPowerTools/DocumentAssembler.cs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/OpenXmlPowerTools/DocumentAssembler.cs b/OpenXmlPowerTools/DocumentAssembler.cs
index f4d9673e..394f4fb8 100644
--- a/OpenXmlPowerTools/DocumentAssembler.cs
+++ b/OpenXmlPowerTools/DocumentAssembler.cs
@@ -483,6 +483,7 @@ private static string ValidatePerSchema(XElement element)
                                   <xs:element name='Table'>
                                     <xs:complexType>
                                       <xs:attribute name='Select' type='xs:string' use='required' />
+                                      <xs:attribute name='Optional' type='xs:boolean' use='optional' />
                                     </xs:complexType>
                                   </xs:element>
                                 </xs:schema>",
@@ -521,6 +522,7 @@ private static string ValidatePerSchema(XElement element)
                                       <xs:attribute name='Select' type='xs:string' use='required' />
                                       <xs:attribute name='Match' type='xs:string' use='optional' />
                                       <xs:attribute name='NotMatch' type='xs:string' use='optional' />
+                                      <xs:attribute name='Optional' type='xs:boolean' use='optional' />
                                     </xs:complexType>
                                   </xs:element>
                                 </xs:schema>",
@@ -692,6 +694,10 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr
                     }
                     if (tableData.Count() == 0)
                         return CreateContextErrorMessage(element, "Table Select returned no data", templateError);
+
+                    var optionalString = (string)element.Attribute(PA.Optional);
+                    bool optional = (optionalString != null && optionalString.ToLower() == "true");
+
                     XElement table = element.Element(W.tbl);
                     XElement protoRow = table.Elements(W.tr).Skip(1).FirstOrDefault();
                     var footerRowsBeforeTransform = table
@@ -720,7 +726,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr
                                         string newValue = null;
                                         try
                                         {
-                                            newValue = EvaluateXPathToString(d, xPath, false);
+                                            newValue = EvaluateXPathToString(d, xPath, optional);
                                         }
                                         catch (XPathException e)
                                         {
@@ -750,6 +756,8 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr
                     string xPath = (string)element.Attribute(PA.Select);
                     var match = (string)element.Attribute(PA.Match);
                     var notMatch = (string)element.Attribute(PA.NotMatch);
+                    var optionalString = (string)element.Attribute(PA.Optional);
+                    bool optional = (optionalString != null && optionalString.ToLower() == "true");
 
                     if (match == null && notMatch == null)
                         return CreateContextErrorMessage(element, "Conditional: Must specify either Match or NotMatch", templateError);
@@ -760,7 +768,7 @@ static object ContentReplacementTransform(XNode node, XElement data, TemplateErr
                    
                     try
                     {
-                        testValue = EvaluateXPathToString(data, xPath, false);
+                        testValue = EvaluateXPathToString(data, xPath, optional);
                     }
 	                catch (XPathException e)
                     {