DS Server

Document Information

Topic

Before your application merges data into a template, it often needs to know what the template expects: which merge fields it contains, which merge blocks repeat and how they are nested. The info endpoint of the DocumentProcessing Web API reads a document and returns this structure together with the document properties, such as the title and the author, without changing the document. A second endpoint lists the printers installed on the server, whose names you can pass as the formatting printer of a merge.

How Document Information Works

The endpoint is POST /documentprocessing/document/info:

Part of the requestContent
BodyThe document as a Base64 string in a JSON string, with the content type application/json
ResponseA JSON object of the type DocumentInfo

The response describes the document as a whole and its merge structure:

PropertyContent
mergeFieldsThe merge fields of the document. Each has a name, and the formats and texts dateTimeFormat, numericFormat, preserveFormatting, text, textBefore and textAfter
mergeBlocksThe merge blocks, each with its name, its own mergeFields and the mergeBlocks nested in it
userDocumentPropertiesThe user-defined document properties, as names and values
documentTitle, documentSubject, documentKeywordsThe title, the subject and the keywords, documentKeywords as an array of strings
author, creatorApplicationThe author and the application that created the document
creationDate, lastModificationDateThe dates of creation and of the last change

A merge field is a placeholder that a merge replaces with a value from the data, and a merge block is a part of the template that the merge repeats for each record of an array, such as a table row per order item. The fields of a block are listed with the block, and each block lists only its own fields and blocks, not those of the blocks nested in it. Merging Templates shows how the structure maps to JSON data.

Every request needs an access token, as Authentication describes.

Read the Structure of a Template With curl

The following commands send template.docx to the info endpoint and print the merge fields and blocks:

DS=http://localhost:5000
TOKEN="<access_token>"

# Wrap the Base64 string of the template in a JSON string
base64 -w 0 template.docx | jq -Rs . > template.json

curl --request POST "$DS/documentprocessing/document/info" \
  --header "Authorization: Bearer $TOKEN" \
  --header "Content-Type: application/json" \
  --data-binary @template.json \
  --output info.json

jq '{mergeFields: [.mergeFields[].name], mergeBlocks}' info.json

The commands work as follows:

  • base64 -w 0 encodes the file without line breaks, and jq -Rs . makes a JSON string of it. The body is this string alone, not an object around it.
  • The response is JSON, not Base64: info.json holds the DocumentInfo object as it is.
  • The last jq command prints the names of the top-level merge fields and the merge blocks with their fields.

When DS Server runs on Linux, the Core build supports the document formats DOCX, HTML, PDF and XLSX only, as Limits on Linux lists. Send templates in one of these formats there.

Read the Structure of a Template With .NET

The package TXTextControl.DocumentServices.DocumentProcessing returns the response as a DocumentInfo object. The following console application prints the properties and the merge structure of template.docx, with nested blocks indented:

using TXTextControl.DocumentServices.DocumentProcessing;
using TXTextControl.DocumentServices.DocumentProcessing.OAuth;

var oauthSettings = new OAuthSettings("<client ID>", "<client secret>");
var documentProcessing = new DocumentProcessing("http://localhost:5000", oauthSettings);

byte[] template = File.ReadAllBytes("template.docx");
DocumentInfo info = await documentProcessing.Info(template);

Console.WriteLine($"Title: {info.DocumentTitle}, author: {info.Author}");

// Merge fields of the document
foreach (MergeField field in info.MergeFields)
{
    Console.WriteLine($"Field: {field.Name}");
}

// Merge blocks with their fields and nested blocks
foreach (MergeBlock block in info.MergeBlocks)
{
    PrintBlock(block, 0);
}

void PrintBlock(MergeBlock block, int level)
{
    string indent = new string(' ', level * 2);
    Console.WriteLine($"{indent}Block: {block.Name}");

    foreach (MergeField field in block.MergeFields)
    {
        Console.WriteLine($"{indent}  Field: {field.Name}");
    }

    foreach (MergeBlock nested in block.MergeBlocks)
    {
        PrintBlock(nested, level + 1);
    }
}

The code works as follows:

  • The DocumentProcessing constructor takes the service URL and the credentials of a security profile that allows the client credentials grant type, and requests an access token.
  • Info sends the document as a byte array and returns a DocumentInfo. Its properties are those of the JSON response in Pascal case: MergeFields, MergeBlocks, DocumentTitle, Author, CreationDate and so on.
  • MergeBlock has a Name, its MergeFields and its nested MergeBlocks, so the method PrintBlock calls itself for each nested block.

The classes are listed in the DocumentProcessing namespace of the .NET API.

Check a Template Before a Merge

The merge structure lets your application check a template before it merges it, for example a template that a user uploaded:

  • Compare the field names with your data. Merge fields are named like the properties of a record. Collect the names from mergeFields and from every block, and compare them with the keys of your JSON records.
  • Match blocks with arrays. A merge block is repeated for each element of a nested array, such as a block OrderItems for the order items of a customer. Check that your data has an array for each block.
  • Build a form or a data mapping. The field names are the list of values a user has to provide, and dateTimeFormat and numericFormat show how a field formats its value.

List the Printers Installed on the Server

A merge can format the document with the text dimensions and capabilities of a printer, the formatting printer. GET /documentprocessing/document/installedprinters returns the printers installed on the server that runs DS Server, as an array of PrinterInfo objects:

curl --request GET "$DS/documentprocessing/document/installedprinters" \
  --header "Authorization: Bearer $TOKEN"

The merge settings of the merge and find-and-replace endpoints have a formattingPrinter property that takes the name of one of these printers, as the reference of POST /documentprocessing/document/merge lists. The endpoint was added in version 3.3.0; the changelog of that version names it document/printers, but DS Server 5.0.2 answers that address with 404 Not Found and serves the list at document/installedprinters.

In .NET, the method InstalledPrinters of the package returns the list as a PrinterInfo array, and the Name property of each element holds the name of the printer:

PrinterInfo[] printers = await documentProcessing.InstalledPrinters();

foreach (PrinterInfo printer in printers)
{
    Console.WriteLine(printer.Name);
}

In version 5.0.0 of the package, a refused request of this method throws a plain Exception, not the ServiceRequestException of the other methods, and the exception has no status code. Errors and Status Codes shows how the other methods report errors.

Next Steps