Merge field containing a dot within a mail merge region

This is using version 13.8.0.0 of Aspose.Words, having upgraded from an earlier version (from about a year ago) which didn’t have this issue.

I have a document with a mail merge region (TableStart:Collection - TableEnd:Collection). Inside this region is a field containing a dot (e.g. “Item.Name”).

I’m calling Document.MailMerge.ExecuteWithRegions(IMailMergeDataSource) with my own implementation of IMailMergeDataSource that iterates through the collection and knows how to interpret “Item.Name” for each item in the collection.

When I execute that code, Aspose.Words calls GetChildDataSource(“Item”) on my IMailMergeDataSource implementation. I would expect (as happens in the earlier version) that it would call GetValue(“Item.Name”) instead.

Is this change in behaviour by design, and is it documented anywhere?

Hi there,

Thanks for your inquiry. It would be great if you please share following detail for investigation purposes.

  1. Please attach your input Word document.
  2. Please attach the output Word file that shows the undesired behavior.
  3. Please
    create a standalone/runnable simple application (for example a Console Application Project) that demonstrates the code you used to generate
    your output document
  4. Please
    attach your target Word document showing the desired behavior. You can
    use Microsoft Word to create your target Word document. I will
    investigate as to how you are expecting your final document be generated
    like.

Unfortunately,
it is difficult to say what the problem is without the Document(s) and
simplified application. We need your Document(s) and simple project to
reproduce the problem. As soon as you get these pieces of information to
us we’ll start our investigation into your issue.

Hi again,

Attached is a sample project containing an example Word document.

Notice the “Item.Name” field in the second column. I expected this to be interpreted as a single field by Aspose.Words. As you can see from the exception thrown when you run the program, it interprets “Item” as another table/region field.

Hi there,

Thanks for sharing the detail. Please note Aspose.Words mail merge engine invokes IMailMergeDataSource.GetChildDataSource method when it encounters a beginning of a nested mail merge region.

When the Aspose.Words mail merge engines populates a mail merge region with data and encounters the beginning of a nested mail merge region in the form of MERGEFIELD TableStart:TableName, it invokes GetChildDataSource on the current data source object. Your implementation needs to return a new data source object that will provide access to the child records of the current parent record. Aspose.Words will use the returned data source to populate the nested mail merge region.

Following code example shows how to perform mail merge from a custom data source. Hope this helps you. Please let us know if you have any more queries.

// Create some data that we will use in the mail merge.
CollectionList collection = new CollectionList();
collection.Add(new Collection("Column 1 Value", "Column 2 dotted value"));
collection.Add(new Collection("Column 1 Value", "Column 2 dotted value"));
collection.Add(new Collection("Column 1 Value", "Column 2 dotted value"));
collection.Add(new Collection("Column 1 Value", "Column 2 dotted value"));
// Open the template document.
Document doc = new Document(MyDir + "TestMergeTemplate.docx");
// To be able to mail merge from your own data source, it must be wrapped
// into an object that implements the IMailMergeDataSource interface.
TestDataSource DataSource = new TestDataSource(collection);
// Now you can pass your data source into Aspose.Words.
doc.MailMerge.ExecuteWithRegions(DataSource);
doc.Save(MyDir + "Out.docx");
class TestDataSource : IMailMergeDataSource
{
    public TestDataSource(CollectionList collection)
    {
        mCollection = collection;
        // When the data source is initialized, it must be positioned before the first record.
        mRecordIndex = -1;
    }
    /// 
    /// The name of the data source. Used by Aspose.Words only when executing mail merge with repeatable regions.
    /// 
    public string TableName
    {
        get { return "Collection"; }
    }
    /// 
    /// Aspose.Words calls this method to get a value for every data field.
    /// 
    public bool GetValue(string fieldName, out object fieldValue)
    {
        switch (fieldName)
        {
            case "SimpleName":
                fieldValue = "Simple item name";//mCollection[mRecordIndex].SimpleName;
                return true;
            case "Item.Name":
                fieldValue = "Dotted item name";//mCollection[mRecordIndex].ItemName;
                return true;
            default:
                // A field with this name was not found, 
                // return false to the Aspose.Words mail merge engine.
                fieldValue = null;
                return false;
        }
    }
    /// 
    /// A standard implementation for moving to a next record in a collection.
    /// 
    public bool MoveNext()
    {
        if (!IsEof)
            mRecordIndex++;
        return (!IsEof);
    }
    public IMailMergeDataSource GetChildDataSource(string tableName)
    {
        return null;
    }
    private bool IsEof
    {
        get { return (mRecordIndex >= mCollection.Count); }
    }
    private readonly CollectionList mCollection;
    private int mRecordIndex;
}
/// 
/// An example of a "data entity" class in your application.
/// 
public class Collection
{
    public Collection(string aSimpleName, string anItemName)
    {
        mSimpleName = aSimpleName;
        mItemName = anItemName;
    }
    public string SimpleName
    {
        get { return mSimpleName; }
        set { mSimpleName = value; }
    }
    public string ItemName
    {
        get { return mItemName; }
        set { mItemName = value; }
    }
    private string mSimpleName;
    private string mItemName;
}
/// 
/// An example of a typed collection that contains your "data" objects.
/// 
public class CollectionList : ArrayList
{
    public new Collection this[int index]
    {
        get { return (Collection)base[index]; }
        set { base[index] = value; }
    }
}

Hi again,

Thank you for taking a look at the code. I didn’t create an actual collection inside the IMailMergeDataSource implementation because my question was more about how and when GetChildDataSource gets called.

I notice your implementation of GetChildDataSource simply returns null. But if you put a breakpoint on that line, you’ll see it gets called with tableName set to “Item”. There is no “TableStart:Item” merge field in the source document, and so I do not expect that to be called. I’m inferring that Aspose.Words treats the dot as a special character (if you replace it with a dash there’s no call to GetChildDataSource(“Item”)).

If I return null from GetChildDataSource, the next method that gets called is GetValue(“Item.Name”). But if I return another IMailMergeDataSource, the method that gets called on that is GetValue(“Name”). So the dot enables (but doesn’t force) the IMailMergeDataSource to pass the part following the dot to another data source.

There might be a certain logic to that behaviour, but it’s a change from our earlier version of Aspose.Words and I can’t find it documented. It’s not obvious how to work with this ‘child’ data source. Do you know when and why this behaviour was added?

Hi there,

Thanks for sharing the detail. I have managed to reproduce the same issue at my side. I have logged this issue as WORDSNET-9061 in our issue tracking system. I have linked this forum thread to the same issue and you will be notified via this forum thread once this issue is resolved. We apologize for your inconvenience.

Moreover, the Aspose.Words mail merge engine invokes GetChildDataSource
method when it encounters a beginning of a nested mail merge region.
When the Aspose.Words mail merge engines populates a mail merge region
with data and encounters the beginning of a nested mail merge region in
the form of MERGEFIELD TableStart:TableName, it invokes
GetChildDataSource on the current data source object. Your
implementation needs to return a new data source object that will
provide access to the child records of the current parent record.
Aspose.Words will use the returned data source to populate the nested
mail merge region.

Below are the rules that the implementation of GetChildDataSource must follow.

  • If the table that is represented by this data source object has a related child (detail) table with the specified name, then your implementation needs to return a new IMailMergeDataSource object that will provide access to the child records of the current record. An example of this is Orders / OrderDetails relationship. Let’s assume that the current IMailMergeDataSource object represents the Orders table and it has a current order record. Next, Aspose.Words encounters “MERGEFIELD TableStart:OrderDetails” in the document and invokes GetChildDataSource. You need to create and return a IMailMergeDataSource object that will allow Aspose.Words to access the OrderDetails record for the current order.
  • If this data source object does not have a relation to the table with the specified name, then you need to return a IMailMergeDataSource object that will provide access to all records of the specified table.
  • If a table with the specified name does not exist, your implementation should return null.

Hi there,

Thanks for your patience.

Regarding WORDSNET-9061,
it is to update you that our development team has completed the
analysis of this issue and has come to a conclusion that they won’t be
able to implement the fix to this issue. Your issue has been closed with ‘‘Won’t Fix’’ resolution.

Please do not use dot (.) in mail merge field name. We will update our documentation about this detail that the dot should not be used in the mail merge field names.

Hello,

we are facing the same problem in the Java version. In our case, the dot is
used to reflect hierarchical structures in the data. As there are a huge
number of templates already in use by the customer, changing that
behaviour is not a feasible solution for us.

Is it possible to add an option to revert to the old behaviour allowing to have dots in the names of merge fields?

Thanks & regards

Hi Sten,

Thanks for your inquiry. The Aspose.Words mail merge engine invokes IMailMergeDataSource.getChildDataSource method when it encounters a beginning of a nested mail merge region.

Please do not use dot (.) in mail merge field name. This is by design. For example, after loaded data source in DataSet with two related DataTable: Orders and Addresses
For rendering Address is used template like:

{{#foreach Order}}
{{Address.Number}} {{Address.Street}}
{{/foreach Order}}

So, if your template has mail merge filed e.g Item.Name, Aspose.Words can not determine at the time of field “Item.Name” mailmerge - is this field name “Item.Name” or is this related object “Item” with property “Name”.

Hope this answers your query. Please let us know if you have any more queries.

The dot in the merge fields was working perfectly well in Aspose Versions 10.5.0.0 and prior.

If I understand you correctly, there is a new functionality which resolves data structures using this “.” syntax. As we do not require this functionality but would prefer to handle this reference resolving by our self, we would like to have a switch to disable the new functionality and thus re-enabling the possibility to use dots in merge fields.

Removing the dots from the merge fields is not a doable solution as there are hundreds of affected templates at the customers each having dots in nearly every merge field.

Hi Sten,

Thanks for your inquiry. We always encourage our customers to use the
latest version of Aspose.Words as it contains newly introduced
features, enhancements and fixes to the issues that were reported
earlier.

Unfortunately, I have to say that it is a desirable behavior and we are not about to change it back. Please check the developer’s reply from here:
https://forum.aspose.com/t/48429

This thread is over a month old, but I want to reference it directly for the issue of the desirable behavior.
With the information in this thread and a couple of other threads I have searched, the interpretation for me, is that you no longer support the new mail merge syntax defined in performance-enhancements-a-complete-list-of-supported-features-and-support-for-new-mail-merge-syntax-in-aspose.words-11.2.0. This defines usage of mustache syntax and the ability to use the “.” notation. Am I reading correctly that this feature is no longer supported? Or does this indicate that creating a merge field created normally through the field dialog and naming with the “.” notation is no longer supported? For me, I am using Aspose.Words Java 13.12. The merge does work for me as I expect with this version using object.attribute within the mustache syntax. However, if this is not going to be supported going forward, I want to know so I can prevent users from defining more documents with this syntax. I already have documents with this syntax in use. It would be a shame to eliminate this as an option since it has great value. Hopefully, I am misinterpreting this. Please clarify.

Hi James,

Thanks for your inquiry. Aspose.Words does support Mail Merge and “Mustache” Template Syntax for Mail Merge.

*jrsaspose:

Or does this
indicate that creating a merge field created normally through the field
dialog and naming with the “.” notation is no longer supported?*

It is not recommended to use “.” in mail merge field name. Please do not use dot (.) in mail merge field name and check following forum link for detail:
https://forum.aspose.com/t/48429

Thank you for the reply. The link you provided is the same link I referenced which is more of a release note for a specific version. I had looked in the programmers guide documentation and could not find the information on the Mustache Syntax. It would be nice to have a topic on that listed in the documentation with additional clarification on when “.” notation can and cannot be used. It might help limit the confusion on the topic.
One other item of confusion regarding the “.” notation is the fact that the link we have referenced indicates that the notation works for “regular merge fields as well.” Based on what you are telling me, this use for regular merge fields is not recommended.

Hi James,

Thanks for your inquiry.

*jrsaspose:

It would be nice to have a topic on that listed in the documentation with additional clarification on when “.” notation can and cannot be used. It might help limit the confusion on the topic.*

We will add article about using mustache merge fields in documentation. Using dot (.) in mail merge field is not related to mustache merge field only. It is not recommended to use “.” in mail merge field name either it is mustache merge field or not.

*jrsaspose:

One other item of confusion regarding the “.” notation is the fact that the link we have referenced indicates that the notation works for “regular merge fields as well.” Based on what you are telling me, this use for regular merge fields is not recommended.*

IMailMergeDataSource.GetChildDataSource is called when mail merge filed contains dot (.) which is incorrect behavior.

IMailMergeDataSource.GetChildDataSource is used to get child(or related) object property value.

For example, after loaded data source in DataSet with two related DataTable: Orders and Addresses
For rendering Address is used template like:

{{#foreach Order}}
{{Address.Number}} {{Address.Street}}
{{/foreach Order}}

So, if your template has mail merge filed e.g Item.Name, Aspose.Words can not determine at the time of field “Item.Name” mailmerge - is this field name “Item.Name” or is this related object “Item” with property “Name”.

Hope this answers your query. Please let us know if you have any more queries.

What you are saying does make sense that you can’t determine field name versus object.attribute. However, with that being said, I am not using the standard DataSet and DataTable. I am using an XML document as input (similar to the Aspose examples) instead of the normal data source. I am trying to determine if using the dot notation will in some way be changed so that I cannot use it in the future from the context of an XML source. I’ve already pushed out documentation indicating it was an option to use that syntax in the document template.

Since Aspose is essentially closed source, I cannot see how the parsing is occurring or when the call to getChildDataSource occurs within the MailMerge implementation to know whether the dot notation will be a problem. At this point, when I use the dot notation syntax, the XML child node (current_node.child) is retreived as expected (e.g. Address.Street). In the context of the XML source, is dot notation incorrect behavior (I’m trying to use proper behavior to prevent future problems)? If it’s incorrect behavior, what is the option to get that child node when it is not a repeating group and it’s not on the same node level as the context node? And, if I go down to the child node, can I get back to the prior context level to continue processing? The IMailMergeDataSource interface does not provide a getParentDataSource method to move back up to the processing context and realistically should not depending on the MailMerge implementation. For this implementation, I have found the dot notation useful to grab that child node’s data without wrapping in TableStart and TableEnd markers. If I use a TableStart and TableEnd to get down to the child level, the problem I run into is crossing section breaks. How should I be operating?

Hi James,

Thanks for your inquiry.

Well, Aspose.Words fully support mail merge and mail merge with regions. Please do not use dot (.) in mail merge field name. This is by design. I suggest you please read the rules when marking a region form here:
https://docs.aspose.com/words/net/types-of-mail-merge-operations/

The Aspose.Words mail merge engine invokes GetChildDataSource
method when it encounters a beginning of a nested mail merge region.
When the Aspose.Words mail merge engines populates a mail merge region
with data and encounters the beginning of a nested mail merge region in
the form of MERGEFIELD TableStart:TableName, it invokes
GetChildDataSource on the current data source object. Your
implementation needs to return a new data source object that will
provide access to the child records of the current parent record.
Aspose.Words will use the returned data source to populate the nested
mail merge region.

Below are the rules that the implementation of GetChildDataSource must follow.

  • If
    the table that is represented by this data source object has a related
    child (detail) table with the specified name, then your implementation
    needs to return a new IMailMergeDataSource object that will provide
    access to the child records of the current record. An example of this is
    Orders / OrderDetails relationship. Let’s assume that the current
    IMailMergeDataSource object represents the Orders table and it has a
    current order record. Next, Aspose.Words encounters “MERGEFIELD
    TableStart:OrderDetails” in the document and invokes GetChildDataSource.
    You need to create and return a IMailMergeDataSource object that will
    allow Aspose.Words to access the OrderDetails record for the current
    order.
  • If this data source object does not
    have a relation to the table with the specified name, then you need to
    return a IMailMergeDataSource object that will provide access to all
    records of the specified table.
  • If a table with the specified name does not exist, your implementation should return null.

Hope this answers your query. Please let us know if you have any more queries.

I did read the Mail Merge with Regions explained when I first started using the product. I am trying to stay in the context of what is supported so I don’t have future migration problems. I definitely understand, based on the threads I’ve read, the dot notation should be avoided.
With that being said, are there separate considerations for a data source that is XML? XML can be defined many ways and typically has many more children than a typical data source such as a database. I still go back to the reference to Mustache Syntax for Mail Merge (https://blog.aspose.com/2012/04/03/support-for-new-mail-merge-syntax-in-.net-and-java-word-processing-api/) which is the only reference I could find regarding the syntax. Looking at the example, this indicates the dot notation is supported with an XML data source. The example there shows Street is a child element of Address but appears to also be acceptable as an attribute for the object.attribute syntax (Nelson Street…). For that XML, the example shows a defined field for “MERGEFIELD Address.Street”. This is how I am using the syntax now and would like to continue and be a supported configuration. The problem is that that usage appears to be contradictory to what you are telling me “Please do not use dot in mail merge field name.” I would guess that if street was an actual element attribute (), which is not how XML should be used, the object.attribute should work also. At least I would hope so.
If I go by the rules you are stating in your last post, this should be defined as a merge region of TableStart:Address and a merge field of Street. I could buy off on that except for the fact that the TableStart and TableEnd markers must be inside of the same section. I have some use cases in which the definition would cross a section boundary. The use case will not work using the Table markers due to crossing section boundaries, but will work using the dot notation. What options are available for a use case such as this if we can’t use the dot notation and have to cross sections? None of the documentation indicates how to solve this problem. In the case of a database as a source, I see where there could be problems. It would be nice to have the ability to cross section boundaries either way.

Hi James,

Thanks for your inquiry. Please note that the issue discussed in this thread is ‘IMailMergeDataSource.GetChildDataSource is called when mail merge filed contains dot (.)’.

If you are using IMailMergeDataSource.GetChildDataSource then do not use dot (.) in mail merge fields. Implement IMailMergeDataSource interface to allow mail merge from a custom data source, such as a list of objects. Master-detail data is also supported.

However, you can use dot (.) in mail merge fields either you are using “Mustache” Template Syntax or not. Please check the following mail merge templates and XML example.

«TableStart:Order»
«Number»
«Address.Street»
«Address.Suburb»
«Address.City»
«TableEnd:Order»
----------------------------------------------------------------------

{{#foreach Order}}
{{Number}}
{{Address.Suburb}} {{ Address.City}} {{Address.Street}}
{{/foreach Order}}

----------------------------------------------------------------------

XML :

<Order> 
<Number>23</Number> 
    <Address> 
        <Street>Nelson Street</Street> 
        <Suburb>Howick</Suburb> 
        <City>Auckland</City> 
    </Address> 
</Order>

The above template works with XML (data source). Please use the following code example to check these templates. Please use MailMerge.UseNonMergeFields value as true, if you are using “Mustache” Template Syntax. I have attached the input and XML files with this post for your kind reference.

Hope this answers your query. Please let us know if you have any more queries.

DataSet ds = new DataSet();
ds.ReadXml(MyDir + "Orders.xml");
// Open a template document.
Document doc = new Document(MyDir + "Invoice Template.docx");
doc.MailMerge.UseNonMergeFields = true;
// doc.MailMerge.UseNonMergeFields = false; 
// Execute mail merge to fill the template with data from XML using DataSet.
doc.MailMerge.ExecuteWithRegions(ds);
// Save the output document.
doc.Save(MyDir + "Out.docx");

I guess I have been having difficulty undertanding the difference between the two scenarios that you are trying to explain. It seems to me that the same terminology is being used on both scenarios. Based on how you describe both scenarios, I believe I am matching both scenarios. For the second example and the attachements you have given, I am using XML similar to the example. I am also defining the template just as the attachment templates indicate with dot notation. Sometimes I’ve defined my templates like the first template and others have been defined like the second template or a combination of both. However, going back to the first scenario (for not using dot), you state “If you are using IMailMergeDataSource.GetChildDataSource then do not use dot (.) in mail merge fields. Implement IMailMergeDataSource interface to allow mail merge from a custom data source, such as a list of objects. Master-detail data is also supported.” It turns out I am implementing an IMailMergeDataSource interface and implementing the GetChildDataSource method. This matches what you are indicating I should not do. For your statement, in what context are we talking about not using dot in the mail merge fields? Inside a code block? Inside the Word document? Or some other context?
Am I to understand that the differentiation you are trying to identify is using the dot notation in the context of an actual code block of the GetChildDataSource method (e.g. Using dot notation as a test for an if statement such as if(Address.Street == “abc”))? If this is the case, it would be helpful to indicate in documentation “then do not use dot notation in the code to reference a mail merge field.” The second scenario is using dot notation in a mail merge field, but within the context of a Word document. If your explanation is to indicate the fact that I created any implementation of the GetChildDataSource method that I should not be using dot notation, then I am not using the IMailMergeDataSource correctly? However, if that’s a problem, the examples in the programmers guide are incorrect.
I definitely want to be clear on what is supported and what is not supported. If this is as significant of an issue as it appears to be, more documentation would be helpful. Maybe your documentation can show an example of what’s not supported. I have yet to see a clear example of what shouldn’t be done in the documentation.
~~~~
As I wrote all of this, I looked back on the thread once again. I believe I have figured out the scenario you are trying to prevent may be in the getValue method, not the getChildDataSource. Is that where the dot notation should not be used? Is there anywhere else? It seems that quite a bit more information should be given in the programmers guide to help people be compliant with the Aspose usage and what should or shouldn’t be done. I left the text above in case I have not interpreted correctly.v