Automating Adobe InDesign 2019 - AppleScript


XML Create Template From Document

Tuesday, August 20, 2019

Creating an XML Template from an Existing Document

In the last two posts we created an InDesign template for importing XML files. In the first, a script created the template from scratch, in the second, we started with a document and used the script to add and map the XML tags. Chances are you may have a document that you have created and later decide to set it up for XML import. In this blog we will demonstrate how this can be done. To start, you will need to make sure the document is set up to facilitate the process.

Document Setup

To support XML import the sample document needs to be set up as follows:

  1. All of the child elements for a parent XML element need to reside in a single text frame or threaded text frames
  2. Paragraph styles need to be named consistent with XML naming convention (no spaces or special characters)
  3. All text styling needs to be with Paragraph and character styles. A nested paragraph style can be used as has been done in the sample document for the dollar amount
  4. The image to be imported needs to be sized to fit within the text frame column and will reside in a folder named Images inside the same folder as the XML file to be imported.

XML Tagging

To set this document up for XML import manually takes a little doing.

  1. Create an XML tag for the enclosing text frame
  2. Select each paragraph in order and create an XML tag with the same name as its paragraph style. Note: Make sure that you do not select the paragraph return at the end of the paragraph.

Import XML

Remember that XML structure starts with a root element with each major element represented in a parent-child relationship. For our sample document there is only one major XML element resulting in the following structure.

Root
    Products
	Product
	    Image
	    Brand
	    Name
	    Desc
	    Price
	    Color
            Packaging
	    Details
        Product
    Products
Root

The XML text file will need to be structured as shown above. With the document open, choose Import XML from InDesign's file menu. If the XML file is correctly formed it will import into InDesign's Structure pane for the document. (Open the Structure pane using the keyboard shortcut Command+Option+1.)

XML document structure...document XML structure

The XML tagging is added to the document but, as you can see, the text is not styled

showing tagged document with XML file imported but not styled...Document tagged but not styled

To add text styling you will next need to map the XML tags to the corresponding paragraph styles.Map Styles

If the Tags panel is not open, choose Utilities > Tags from InDesign's Window menu. From its menu select Map Tags to Styles.

Menu to open tags panel...Open Map Tags to Styles panel

For each child XML element in the Structure pane named the same as a paragraph style, select the paragraph style name to correspond.

shows mapping XML tags to paragraph styles...Mapping XML tag to paragraph style

The good news is that once you have connected the Product element to its main container and mapped tags to styles these will save with the document. With this done you will want to save the document as a template, ready to receive the next XML import.

shows the document after mapping tags to styles...After mapping tags to styles

Demonstration Script

If creating tags and mapping tags to styles seems like a lot of work. You can use the following script to perform the work for you. It's almost magic. Open the document to be modified, select the container for the story to be tagged, and run the script. Enter the tag name for the story when prompted and the script does the work for you.

Get Selected Container

try
    set frameRef to textFrameSelected()
on error errStr
    activate
    display alert "Error: " & errStr
end try

(*Returns reference to text frame if frame or insertion point is selected.*)
on textFrameSelected()
    tell application "Adobe InDesign CC 2019"
	set selList to selection
	if length of selList = 0 then
	     error "Requires text frame or insertion point selection"
	end if
	if class of item 1 of selList = text frame then
	    set frameRef to item 1 of selList
	else if class of item 1 of selList = insertion point then
	    set frameRef to item 1 of parent text frames of item 1 of selList
	else
	    error "Requires text frame or insertion point selection"
	end if
    end tell
    return frameRef
end textFrameSelected

Get Tag Name for Container

Define the following variables at the top of the script above:

    set promptStr to "Enter tag for story element"
    set displayTitle to "XML Tag"
    set dAnswer to "Product"

Add the following statement before the on error statement in the script above:

    set tagName to getString(promptStr, dAnswer, displayTitle)

Add the handler at the bottom of the script.

(*Gets string response from user; otherwise throws error*)
on getString(promptStr, dAnswer, displayTitle)
    set userResponse to display dialog promptStr default answer dAnswer default button 2
    if text returned of userResponse = "" then
	error "Valid string not entered"
    end if
    return text returned of userResponse
end getString

Tag Selected Frame

Next, the script creates XML elements for mapping the selected text frame. Add this statement before the on error statement above:

    set parentElement to tagFrame (frameRef, tagName)

This calls a handler named tagFrame which in turn calls a handler (getTag) that adds the needed XML tag to the document. Add these handlers to the script.

(*Creates parent XML elements and associates selected frame with its XML element*)
on tagFrame(frameRef, tagName)
    set masterName to tagName & "s"
    tell application "Adobe InDesign CC 2019"
	set docRef to document 1
	if (count of XML elements of docRef) > 1 then
	    error ("Structure has already been created")
	end if
	set mTagRef to my getTag(docRef, masterName)
	set tagRef to my getTag(docRef, tagName)
	set rootElement to XML element 1 of docRef
	tell rootElement
	    set masterElement to make XML element with properties {markup tag:mTagRef}
	end tell
	tell masterElement
	    set parentElement to make XML element with properties {markup tag:tagRef}
	end tell
	tell parentElement to markup using frameRef
    end tell
    return parentElement
end tagFrame

(*Creates tag given tagName that is checked using checkName handler. If error can return missing value*)
on getTag(docRef, tagName)
    set tagRef to missing value
    tell application "Adobe InDesign CC 2019"
	tell docRef
	    if exists XML tag tagName then
		set tagRef to XML tag tagName
	    else
		set tagRef to make XML tag with properties {name:tagName}
	    end if
	end tell
    end tell
    return tagRef
end getTag

Map Tags to Paragraph Styles

All that is left is to map the paragraph styles to XML tags to implement text styling. A handler named tagParagraphs will go through the paragraphs of the story and map XMl tags of the same name to the styles. Adding a call to this handler, the try block at the top of the script should now read as follows:

try
    set frameRef to textFrameSelected()
    set tagName to getString(promptStr, dAnswer, displayTitle)
    set parentElement to tagFrame(frameRef, tagName)
    tagParagraphs(frameRef, parentElement)
on error errStr
    activate
    display alert "Error: " & errStr
end try

Finally, add the tagParagraphs handler to the bottom of the script

on tagParagraphs(frameRef, parentElement)
    tell application "Adobe InDesign CC 2019"
	set docRef to active document
	set storyRef to parent story of frameRef
	tell storyRef
	    set paraCount to count of paragraphs
	    repeat with i from 1 to paraCount
		set paraRef to object reference of paragraph i
		set styleName to name of applied paragraph style of paraRef
		if styleName is not in {"[Basic Paragraph]"} then
		    set styleRef to paragraph style styleName of docRef
		    set tagRef to my getTag(docRef, styleName)
		    tell parentElement
			set elementRef to make XML element with properties {markup tag:tagRef}
		    end tell
		    set textRef to object reference of text from character 1 to character -2 of paraRef
		    tell elementRef
			markup using textRef
		    end tell
		    tell docRef
			make XML import map with properties {mapped style:styleRef, markup tag:tagRef}
		    end tell
	        end if
	    end repeat
	end tell
    end tell
end tagParagraphs

Onward and Upward

Working with XML takes a little discipline. A simple thing like a mismatched capital for a tag or an image incorrectly sized can cause havoc when it comes to importing your XML file. Until you get comfortable with the process, it is a good idea to open the XML file in a text editor and compare its structure with the document XML structure prior to importing.

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.

Trackback Link
http://www.yourscriptdoctor.com/BlogRetrieve.aspx?BlogID=18424&PostID=1529585&A=Trackback
Trackbacks
Post has no trackbacks.

Recent Posts


Tags

file paths dropdowns grid try/on error reference to random number table styles file info Repeat With Document from Template Chaining Paragraph Styles Styling Text info for measurement editboxes import styles Choose file move file InDesign template giving up after Border Panel XML tags tabs live bounds convert to text Create Document Duplicate Choose from list Place text GREP find change options handlers Buttons Custom Dialog lists Clearing Overrides draw from center StandardAdditions Radiobutton Group Find by Attribute text item delimiters Multi-state objects stacking order Find Text coordinates Image Placement lists of lists Create Text Frame Read text file as list time Script panel Export to PDF bookmarks rest Combobox Library Folder selection Script Preferences sort list script templates date objects CALS tables Placing images Text Style Mapping import text automated workflow image metadata Previous text frame Check for Styles Adding Captions fit XML structure active spread Character Styles Nested Repeat Loops page items Next Style auto tag paragraph styles choose file name static alignment Templates Keyboard Shortcuts Document stylesheets start paragraph repeat loops rest of list integer editboxes import XML Script Library Apply Object Style Write to File Change Text master spread text editbox dialog text import preferences next text frame Autoflow Excel XML intent place point user interaction level entire path Image Events Editbox measurements primary text frame threaded text frames map tags to styles Enabling Groups script folder do script Adjust Layout object styles Checkbox Control Document Presets tab list radiobutton control

Archive