For Adobe InDesign you already know that tables can be imported from Excel and can be created from text that is formatted as tab- or comma-delimited text. When working with XML, the table format of choice is CALS Tables. You have probably noticed the XML import option Import CALS tables as InDesign tables when you started an XML import. And you maybe even wondered how it all works. On the other hand, you may have worked with CALS tables with the satisfaction that you have taken the time to learn its syntax.

…Options for importing XML


The CALS Table model was developed specifically for SGML and XML. So, if you are familiar with writing XML, creating tables with CALS is just a matter of learning the tags and attributes that it uses. With no attempt on our part to cover the subject, you can most likely be successful in just knowing the basics.

  1. A table is wrapped inside
    (table info here)


  2. Three sections for a table are the head (thead), body (tbody), and footer (tfooter)
  3. Inside the three sections you have rows (row) with each cell (entry) wrapped inside a begin and end tag.
  4. Specific to the table are groups (tgroup) which identify the number of columns for a group and a column specifier (colspec) which can be used to name columns, and identify widths. Column widths can be specified numerically as points (pt), inches (in), pi (picas), cm (centimeters), or mm (millimeters); also as proportional or relative numbers followed by an asterisk (colwidth=’1.6*’)
  5. You can merge cells within a row and within a column using morerows= (for merging vertically) and namest= (name start) and namend= (name end) for merging named cells horizontally.
  6. pgwide determines if the table will be the width of the page (‘1’) or the width of the story flow (‘0’)
  7. colsep and rowsep determine if there will be rules between columns and rows respectively (‘0’ is false; ‘1’ is true)

Where the power of the CALS model shows up is with some of its attributes. Similar to HTML, any number of attributes can be assigned to an element inside its beginning tag. You have already been exposed to some in the discussion above, but you can get a complete listing of attributes at http://www.oasis-open.org/specs/a502.htm. A sample XML file to demonstrate some of the CALS table attributes are as follows. We have eliminated entry value and some rows that repeat similar syntax (noted in square brackets] just to keep your eyes from glazing over:

    Cold Brew Coffee System
    Check out the special pricing on these excellent BodyBrew products. Richer, satisfying taste for the customer.  Better ROI for you.
    Ultimate Cold Brew Coffee Maker

[names remaining columns setting their widths to a relative percentage of the total width] Model Item # [entries for remaining columns same as above entry with different header values]
Experience 103784102 BOD 24 oz. Shatter-proof and Spillproof Design. BPA Free Stainless Steel, Dishwasher Safe 25 oz.,75 ml 12345 [4 entry elements specifying morerows=’5′ with valign=’top’; these for remaining columns in row] Sky [4 more row elements with entry elements similar to the row above]
Shipping: FOB Packaging: Master Pack – 24 per case


Notice with this stucture any number of tables could be added to the story.

Reminder: The one thing you need to remember in putting an XML file together is that there are certain characters that XML does not like. These characters, referred to as entities, need to be enclosed within an ampersand on one side and a semicolon on the other. The big nasty that you will run into is the ampersand itself (that can be substituted with the word “and”). Within an XML statement it will look like the following:


Less than (<) and greater than (>) may also find thir way into your XML. Make sure you use the XML entity instead of the character (lt and gt enclosed with an & to the left and a ; to the right).


Our sample script will do the XML import for us but first the script will need to make sure there is a document open. The document will need to be set up with a single text frame tagged to a “story” tag. Paragraph styles will need to be in the document with the following names (to correspond with the XML tags for the XML file defined above): “brand”, “name”, and “desc”. The script will have the user choose the table style to use from a list of table styles in the document. For this reason there will need to be at least one table style defined for the document.

Import XML with Table

(*At the top, set variables and call handlers*)
--dLocation is an alias reference to the default location in which to find the XML project folder
set dLocation to path to desktop from user domain
set fileExt to "xml"
set promptStr to "Select " & fileExt & " file to import"
set stylePrompt to "Select name of table style for styling tables"
   set docRef to getDocRef()
   set fileToImport to chooseFile(dLocation, promptStr, fileExt)
   set styleName to selectStyle(docRef, stylePrompt)
   importXMLFile(docRef, fileToImport, styleName)
on error errMsg
   display alert errMsg
end try

Generic Handlers

Three of the handlers used in this demonstration script can be used in any number of scripts. You may recognize one or two of them:

(*Checks for modal state and returns topmost document if open*)
on getDocRef()
   tell application "Adobe InDesign CC 2019"
	if modal state is true then
	   error "Please close open dialogs and try again"
	end if
	if (count of documents) = 0 then
	   error "Requires an open document."
	end if
	set docRef to document 1
   end tell
   return docRef
end getDocRef

(*Has user choose the XML file for import and tests for the file extension*) 
on chooseFile(dLocation, promptStr, fileExt)
   set fileRef to choose file with prompt promptStr default location dLocation without invisibles and multiple selections allowed
   set fileInfo to info for fileRef
   if name extension of fileInfo is not fileExt then
	error "file of type required not chosen"
   end if
   return fileRef
end chooseFile
*Presents user with choice of names of table styles; errors if user cancels*)
on selectStyle(docRef, stylePrompt)
   tell application "Adobe InDesign CC 2019"
	tell docRef
	   if (count of table styles) = 0 then
		set styleName to "UndefinedStyle"
		make table style with properties {name:styleName}
		set styleNames to name of table styles
		set userChoice to choose from list styleNames with prompt stylePrompt
		if userChoice is false then
		   error ("User cancelled table style choice")
		end if
	   end if
      end tell
      return item 1 of userChoice
   end tell
end selectStyle 

Handlers for XML Import

(*Sets import prefs for merge with CALS tables*)
on setImportPrefs(docRef)
   tell application "Adobe InDesign CC 2019"
      tell XML import preferences of docRef
	 set import style to merge import
	 set ignore unmatched incoming to false
	 set ignore whitespace to false
	 set import CALS tables to true
	 set import text into tables to false
	 set import to selected to false
	 set remove unmatched existing to false
	 set repeat text elements to false
      end tell
   end tell
end setImportPrefs
(*Has uer choose name of table style for styling all tables imported*)
on importXMLFile(docRef, fileToImport, styleName)
   tell application "Adobe InDesign CC 2019"
      tell docRef
	 set styleRef to table style styleName
	 import XML from fileToImport
	 set textFrames to text containers of story 1
	 set frameRef to item 1 of textFrames
	 tell every table of frameRef
	    set applied table style to styleRef
	 end tell
      end tell
   end tell
end importXMLFile 

Here, because there is only one story in this document, the entire structure inside the Root element is enclosed in a single tag, story.

…Structure Pane showing text snippets

Notice that there is no tag for the table in the structure pane. The structure for a table is self-enclosed and becomes part of its parent element. You could have a tables tag to act as the parent of a number of tables. Here we have used the tableHead as the table’s parent. As you can imagine, a document can have any number of tables each with any number of columns and rows. There are limitations with the CALS model however, most notably the lack of support for images. The good news is that once imported, the table is an InDesign table with all of its capabilities at your beck and call.

…The final document with table


Now that you have been introduced to the CALS table model, you may decide that using XML isn’t that hard after all. Try it for your next project that needs tables and perhaps has a lot of repetition. With this last mention, our closing chapter on working with XML will be next week with an introduction to using it with multiple pages and multiple objects. See you then.

Scripts provided are for demonstration and educational purposes. No representation is made as to their accuracy or completeness. Readers are advised to use the code at their own risk.