Repurposing XML statistics for InDesign automation

22 03 2010

Well! I’ve been working on a lovely statistics prototype. Using the latest jQuery, theme rolled to match my employer’s corp ID, and the awesome free trial of Fusion Charts (along with a bit of php and xsl mastery), I’ve made a pretty cool stats prototype website.

All the graphs OR table views are rendered from XML files containing the institution’s statistics, both views support clickable drill downs and the whole interface is slick as, but it stops at on-screen graph/table viewing.. Even though the UI is rich and fun to use (accordion, nice jQuery forms and tabs), I’d like to make it a little more fancy than that. In comes InDesign.

Screenshot of the online statistics prototype I was working on

I don’t have a copy of InDesign server, and I’d love some training in scripting and InDesign server apps, but for the moment I’m working on a scenario with the InDesign CS4 client – here’s what I want to do.

I want a button on the prototype site that says “send me these stats”.. from the user’s perspective, they click it and next thing, an email shows up in their inbox with an attached PDF of beautifully formatted statistics, with the institution’s logo and so on. Sound nice?

From my perspective that means: I’d need the XSL for InDesign to transform the XML used by Fusion Charts and the prototypes XSL (in table view) – which would allow InDesign to import the data as an actual table, already mapped with table and cell styles. Obviously to automate all this and generate/email a final PDF I’d need the InDesign server, but hey, I’m just trying to prove a concept here that it’s doable.

It’s quite easy to import XML in to InDesign and have it all mapped with styles and automatic formatting. Take my XML for example:

<chart caption='Student Load (EFTSL) by Gender' subcaption='2006 Full Year' xaxisname='Student Modes' yaxisname='Student Load' palette='1'>
	<categories>
		<category label='Commencing' />
		<category label='Continuing' />
		<category label='All' />
	</categories>
	<dataset SeriesName='Male'>
		<set value='4275' />
		<set value='6245' />
		<set value='10520' />
	</dataset>
	<dataset SeriesName='Female'>
		<set value='3401' />
		<set value='4532' />
		<set value='7933' />
	</dataset>
	<dataset SeriesName='Both'>
		<set value='7676' />
		<set value='10777' />
		<set value='18453' />
	</dataset>
</chart>

And look at how I’ve done the XSL for InDesign, note the name space defs, in particular the aid5 one which is for the latest version of InDesign only ; )

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/">
<xsl:template match="/">
<xsl:for-each select="chart">
<Root>
<Story>
<h3 aid:pstyle="h3"><xsl:value-of select="@caption"></xsl:value-of></h3>
<h4 aid:pstyle="h4"><xsl:value-of select="@subcaption"></xsl:value-of></h4>

<Table aid:table="table" aid:trows="4" aid:tcols="4" aid5:tablestyle="DataTable">

	<ColHeader aid5:cellstyle="BlankCell" aid:table="cell" aid:theader="" aid:crows="1" aid:ccols="1" > </ColHeader>

	<xsl:for-each select="categories/category">
		<ColHeader aid5:cellstyle="ColHeader" aid:table="cell" aid:theader="" aid:crows="1" aid:ccols="1" aid:pstyle="TableHeading"><xsl:value-of select="@label"></xsl:value-of></ColHeader>
	</xsl:for-each>

	<xsl:for-each select="dataset">

	<RowHeader aid5:cellstyle="RowHeader" aid:table="cell" aid:crows="1" aid:ccols="1" aid:pstyle="RowHeading">
		<xsl:value-of select="@SeriesName"></xsl:value-of>
	</RowHeader>

	<xsl:for-each select="set">    	
		<Cell aid5:cellstyle="TableBody" aid:table="cell" aid:crows="1" aid:ccols="1" aid:pstyle="TableText">
			<xsl:value-of select="@value"></xsl:value-of>
		</Cell>
	</xsl:for-each>

	</xsl:for-each>

</Table>
</Story>
</Root>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

To get it in to InDesign, it’s quick as, you just import the XML using the above XSL file, easy peasy, and because the XSL transforms the XML in to a format InDesign ‘likes’, the table will be created properly.

Problems are always involved though. So far I haven’t solved these:

  • I had to set the table’s cols and rows manually in the XSL – this is totally not good. You can do all sorts of tricky things with XSL 2.0, so, I’m sure I could put the count of the desired nodes in to a variable and base the column and row count on that.
  • Look at how it comes in to InDesign – the table width!!! Or should I say LACK of table width. I want it to full width the table but I can’t set any static dimensions because the number of columns in tables will always be variable… what to do I’m not quite sure. I could probably create an InDesign script which makes the table the width of the page (within the margins) then distributes the columns evenly? Then again, I could also do some trickery and math in the XSL – count the columns, divide the page width by the number of columns and use the standard cell width in XSL?

Still, it does look promising nonetheless. I’ve seen lots of posts on the net with people having problems getting table data in to InDesign at all, so hopefully the above code snippets and stuff will help some people.

I’ll keep working on this though, and at some point, I’d LOVE to get my mittens on a copy of InDesign server to see what it can do to help me.





Incrementing and logic in XSL

17 11 2009

I’ve been learning XSL for the design of the learning guide I mentioned in my last post. I just had a bit of a win with incrementing in the XSL! I searched the net far and wide and didn’t find anything that suited what I wanted in terms of incrementing, most things didn’t even work anyway.

The XML I’m transforming describes the content in terms of “sections”. The XSL transforms those sections into a jquery tabbed interface. So basically, I need the title attributes of the tab links, to match the id attributes of the div containers. I also need these to be unique for the jquery tabs to work. Thus, I wanted to increment the values.

Here’s a sample of the XML, just a simple example – an item is a module in the learning guide, it contains various information, part of which includes the actual ‘content’ for that module:

<itemContent>
<section title="Start">
<sectionContent>first section of this module</sectionContent>
</section>
<section title="Middle one">
<sectionContent>content for middle section</sectionContent>
</section>
<section title="Finish">
<sectionContent>content for third section here</sectionContent>
</section>
</itemContent>

Then, the XSL that transforms and increments. I had it all around the wrong way initially, I was trying to use variables and addition, loops etc, to do my incrementing.. but really, all I had to do was identify the node position and use that as a parameter in my for-each loop!

<div id="tabs">
	<xsl:for-each select="itemContent/section">                    
		<xsl:param name="i"><xsl:number value="position()" /></xsl:param>
		<a href="#" title="Section_{$i}"><xsl:value-of select="@title" /></a>              		
	</xsl:for-each>
	<div class="clear"></div>
</div>

<xsl:for-each select="itemContent/section">
	<xsl:param name="i"><xsl:number value="position()" /></xsl:param>
	<div id="Section_{$i}" class="hiddencontent">
		<h3><xsl:value-of select="@title" /></h3>
		<xsl:copy-of select="sectionContent" />
	</div>
</xsl:for-each>

It works a charm and it renders like this in the browser:

HTML render of the XSL incrementing

Note the incrementing and matching title/id attributes..





Media-rich Learning Guide

6 11 2009

We had this little problem last year – we really wanted SOMETHING to do an online study/learning guide with.. well not just ‘something’, we wanted it to be media rich in that it is not just visually appealing but allowed all sorts of GUI features (like popups, tabs etc) so that it could have more media-rich content.

The reason at the time was because the course we were working on had SO many resources, from all over the place, and we thought it might be a good thing to bring everything together, in to context.  (and to make it look nice).

I started thinking of ideas for a GUI and realised one of my favourite interfaces would have to be iTunes!  The interface is called cover flow and it’s visually delicious to say the least.

iTunes coverflow

This is the iTunes coverflow GUI, nice hey?

As it turned out, after some searching the net for Flash resources, I found this awesome Open Source Initiative Flash-based cover flow project.  The beauty of it, like the beauty of iTunes, is it basically gets all its data from an XML file.  So that got me thinking.

What if the learning guide was entirely in XML?  Well, why not.  You could request a course code in your web browser, a php page could parse your request to Flash, which then loads the XML learning guide menu in coverflow, and voila, ajax the content in to the page with each click in the flash cover-flow!

I modified the Flash-based coverflow to suite our purpose.  I made the initial course trial static, in that the content was being loaded from html files, and the course-specific XML only contained details on the course topics and titles etc.  Now however I’m working on the full deal, the entire learning guide in XML.  It’s all coming together rather nicely.

HLG

We've nick-named it the HLG (hypertextual learning guide). You select your study module from the coverflow menu, and all the content loads below via ajax. The content sits in the course XML, and the XSL handles the rendering of all the variations in that content. This example has some readings, but there could also be videos, podcasts, all sorts of stuff.

Learning XSL has been a highlight of the last week, I’m still quite a noob at it, but so far I’ve done some awesome things – I can handle all sorts of variations in the XML (which means variations in content) and render it on the page nicely – videos come up with a video icon and use the jQuery prettyBox plugin, documents come up with a document icon, abstracts have the abstract viewable via a jQuery clueTip plugin.. its all coming together.

The setup

I have some more work to do with the XML/XSL, but I think it will all go well. At the end of it, I'll basically have a single php file, that takes course code requests.. the page will talk to a library of standard resources like the images in the cover-flow menu, the background images, css, and javascripts. It'll then talk to the requested XML (via a php transform and XSL file) to get all the details and content.

Phase 3 will be doing an administration interface, to manage the XML.. ohh fun.