I spend my last days researching how to create a multi page document in InDesign by XML import and came across a lot of great sources but had to accept that InDesign lacks more complex importing capabilities. The most limiting factor is clearly that you can’t copy whole pages of an example design for every new data set in the XML — like for example a new page for every new <product> node that gets imported.
So I am not going to explain how XML importing in InDesign is done — you can easily find that with the search engine of your choosing — instead I will assume for this that you know
- how to tag frames
- import XML data into your design
- know the structure panel and
- create XML in accordance to that structure
Tl;dr: I emulated the steps you need to do manually import an XML into your multi page document where every page is the same layout. Since InDesign does not automatically copy frames and their position on a new page, you need to copy & paste the necessary number of pages before importing the XML. This is exactly what I do with this little script, and clean up empty pages and frames after. That simple.
Three steps to import your data
- First flatten your XML. Since we are going to copy the page, the XML structure that InDesign wants to import needs to be flat. It hurts a little but it will be worth it.
<product> -<name>Fubar</name> -<price>42</price>
-<name>Barfu</name> -<price>23</price> -<subtitle>Not so awesome</subtitle>
Will need to look like this:
<subtitle>Not so awesome</subtitle>
- Second create your sample page, place the frames you want where you need them and tag them according to the XML tags so the data will get imported.
3. Copy this script into ExtendScript and run it on your InDesign document. It will copy your first page 20 times (configurable), import the XML only with tags that are present in the document. After that is done the script removes empty frames and after that empty pages.
If everything worked you should have a multi page document with your XML data and your sample page design intact.
If you are interested what the code exactly does here is a quick explanation. In addition you will find comments in the code itself you just copied.
- app.doScript(…) — this kicks of all the other scripts. What is neat about it, it makes everything that happens into one undoable so if something does not work as planned there is no need to undo 50 single steps of everything that happened.
- createDummyPages(20) — copy & pastes the first page 20 times. If a higher number is necessary just change it right there. Don’t set it too high since this takes longer. The script does not yet have a way to set a good numbe beforehand.
- importXMLData(doc) — imports your XML, you can adjust the importsettings and path to the XML file in the function. Be sure to leave ignoreUnmatchedIncoming = true.
- removeBlankFrames(doc) — this function steps through every frame in the document and removes empty ones. I came across an issue that frames that got tags in them (that are necessary for the XML import if you for example have multiple lines of the same tag that need to repeat themselves) will have a content length of 2, even if no content is present. Hence the function checks for content of 2 or less. I realize this is a hack and potential point of failure.
- removeBlankPages(doc) — the same like with the frames just for whole pages.
- reversePageOrder(doc) — for some reason the copy & pasting of the pages creates the order of the XML tags in reverse so that after the import the last page contain the first XML data. This function is my pragmatical solution for that.
I am aware that there is stuff that can be done better but it works for me and since I have not come across anything similar on the web I decided to share my findings like all the other awesome people who’s resources I read to create this one.
If anyone wants to take this script and polish it (maybe a user interface that lets you pick the XML and enter the dummy-page-count or even some script that calculates the number of pages necessary) you are of course free to do so! Drop me a line if you do.