XML TEMPLATES

In our last post we developed an XML solution starting from ‘scratch” using a template specifically for just importing paragraph and object styles. On the other side of the spectrum, a template can provide all of the elements required for an automated XML workflow. This is paeticularly useful for documents that have a repeating publication schedule such as newsletters and product sales sheets where the page layout is consistent.

Consider a typical XML template. It can define XML tags, paragraph and object styles, and possibly structure in addition to the normal the document parameters of size and margins. All that is needed to complete the process is to import an XML text file which has been prepared to comply with the document tags and structure. Let’s see how a template like this can be created.

  1. Create or open an InDesign document. Any document will do as long as it has the basics: size, margins, facing or non-facing pages. For our purpose we will assume it is a single page.
  2. Load or create XML tags. You can load tags from an existing XML text document as long as it has tags named to match the XML elements you will be importing. For our purpose we will import a dummy XML file that has the needed structure for 6 items.
  3. Create or import paragraph styles. Make sure you have paragraph styles with names that match the names of the corresponding XML tags.
  4. Map your XML tags to styles. Only the tags that match paragraph styles need to be mapped.
  5. Create and map page items in your InDesign document to receive the XML items that will be imported.
  6. Add standing page items that will not change with each version of the document.
  7. Save the document as an InDesign template.

Your template should be ready for use.

CREATE DOCUMENTS

To use the template, images for the document will need to be sized and saved in a folder named Images. This folder is placed in the same folder as the XML text file.

All that needs to be done to complete the project is for the user to open the template, save it as an InDesign document, and import the XML file that has been prepared for import.

SAMPLE SCRIPT

Of the seven steps above that are listed for creating a template for XML import, five can be automated with a script. The page items for this template will be a grid of rectangles each of which will house an xML item. The containing area for the grid will be defined by creating and selecting a rectangle on the active page before running the script. The script will have some resemblance to the sample script that was created in our previous blog post but will present some new wrinkles. For simplicity, the values for our variables are placed at the top of the script.

Determine Page Item is Selected

global numRows, numCols, gut, gap
set numRows to 2
set numCols to 3
set gut to 12
set gap to 12
set choosePrompt to "Choose dummy XML file for import"
try
   set selRef to getSelection()
on error errStr
   activate
   display alert ("Error: " & errStr)
end try
(*Returns reference to page item selected if text frame/insertion point or rectangle*)
on getSelection()
   tell application "Adobe InDesign CC 2019"
	set selList to selection
	if selList is not {} and class of item 1 of selList is in {text frame, insertion point, rectangle} then
	   set selItem to item 1 of selList
	else
	   error "Requires text frame or rectangle selection"
	end if
	if class of selItem is insertion point then
	   set storyRef to parent of selItem
	   set frameRef to item 1 of text containers of storyRef
	else
	   set frameRef to item 1 of selList
	end if
	return frameRef
   end tell
end getSelection

Notice that here we are using global variables for our grid parameters. Normally, global variables are discoouraged, but in the event that the variables will not change within the script, they can be used effectively.

Import Dummy XML File

One way to get XML tags and structure is to import an XML file. This can be a dummy file, and doesn’t necessarily need to have the same structure you will be using. All you really need are the names of the elements defined by your XML text file. Add to the above after the call to getSelection():

set fileChoice to choose file with prompt choosePrompt

The reference returned will be used in the handler that sets up the page. Add the call to this handler directly below:

   doSetup (selRef, fileChoice)

Do setup is the workhorse for this script. It imports the XML file, maps tags and creates a grid of containers complete with mark up.

(*Creates page items using boundsList returned from calcGridBounds*)
on doSetup(selRef, fileChoice)
   tell application "Adobe InDesign CC 2019"
      set pageRef to parent of selRef
      set docRef to active document
      tell docRef
	  import XML from fileChoice
	  set rootElement to XML element 1
	  set tagList to name of XML tags
      end tell
      --map tags to styles
      my mapTagsToStyles (docRef, tagList)
      --calculate geometric bounds for page items to be created
      set measurement unit of script preferences to points
      copy geometric bounds of selRef to {y0, x0, y1, x1}
      set celWid to ((x1 - x0) - (numCols - 1) * gut) / numCols
      set celHgt to ((y1 - y0) - (numRows - 1) * gap) / numRows
      set boundsList to my calcGridBounds(x0, y0, celWid, celHgt)
      --create grid of page items of same class as selected item
      set selClass to class of selRef
      tell pageRef
	  repeat with i from 1 to length of boundsList
	      set thisBounds to item i of boundsList
	      set thisItem to make selClass with properties {name:"Container", geometric bounds:thisBounds}
	      set itemElement to XML element i of XML element 1 of rootElement
	      markup thisItem using itemElement
	  end repeat
      end tell
   end tell
end doSetup

Import a dummy XML file to add tags to your doocument…A dummy XML file can provide needed XML tags

All the script needs now are the handlers called from the doSetup handler above: mapStylestoTags and CalcGridBounds.

(*checks to make sure a paragraph style exists for mapping each XML tag to style*)
on mapTagsToStyles(docRef, tagList)
    --we only need to map tags to paragraph styles, the rest we can ignore
    set eList to {"Root", "Item", "Items", "Image"}
    tell application "Adobe InDesign CC 2019"
	tell docRef
	    repeat with i from 1 to length of tagList
		set thisName to item i of tagList
		if thisName is not in eList then
		    if not (exists paragraph style thisName) then
			set styleRef to make paragraph style with properties {name:thisName}
		    else
			set styleRef to paragraph style thisName
		    end if
		    set tagRef to XML tag thisName
		    make XML import map with properties {mapped style:styleRef, markup tag:tagRef}
		end if
	    end repeat
	end tell
    end tell
end mapTagsToStyles
(*Calculates geometric bounds for items within a grid*)
on calcGridBounds(x0, y0, celWid, celHgt)
    set boundsList to {}
    set firstX to x0
    repeat with i from 1 to numRows
	repeat with j from 1 to numCols
	    set x1 to x0 + celWid
	    set y1 to y0 + celHgt
	    copy {y0, x0, y1, x1} to the end of boundsList
	    set x0 to x1 + gut
	end repeat
	set x0 to firstX
	set y0 to y1 + gap
    end repeat
    return boundsList
end calcGridBounds

Compile and run the script. If you did not start with a template that defined paragraph styles, this would be a good time to do it. The styles have been created so, for the most part, you just need to define font, size, leading, justification and perhaps hyphenation.

Finally, add any page elements that are needed that do not change between versions of the document.

..Our template is ready to save

Save the document as an InDesign template giving it a descriptive name to indicate its purpose and perhaps any details such as grid or other.

ONWARD AND UPWARD

You can make this script even more user friendly by providing a custom dialog for entering grid parameters: rows, columns, gutter, and gap. It may take a little extra time to put a script such as this together but the return on investment of time will grow measurably each time the template is used.

…Our document after adding real XML data

Disclaimer:
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.