Search code examples
xmlxsltadobe-indesign

transform dynamic XML to Adobe InDesign table using XSLT


I'm in trouble with transforming an list of XML-items to a indesign-table. One issue is to calculate the number of rows, because this is needed but can't processed as simple count().

The InDesign-table should look like that:

+------------+-------------+------------+
|ARTIKELNR   |BEZEICHNUNG  |VK1BRUTTO   |
+------------+-------------+------------+
|            |TEXT1                     |
+------------+--------------------------+
...

The XML looks like that:

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<kategorie>
  <artikel>
<ARTIKELNR>              200151</ARTIKELNR>
<BEZEICHNUNG>ARTIST ONE - the first release</BEZEICHNUNG>
<TEXT1></TEXT1>
<VK1BRUTTO>13,9900</VK1BRUTTO>
  </artikel>
  <artikel>
<ARTIKELNR>              200153</ARTIKELNR>
<BEZEICHNUNG>ARTIST TWO - the second release</BEZEICHNUNG>
<TEXT1>Lorem ipsum dolor whatever...</TEXT1>
<VK1BRUTTO>13,9900</VK1BRUTTO>
  </artikel>
....

As you can see sometimes TEXT1 is empty. In this case: there is no second row for this item.

Therfore I wrote down this (InDesign)XSLT:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/" exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:strip-space elements="ARTIKELNR"/>
<xsl:template name="rowcount">
  <xsl:param name="rows"/>
  <xsl:for-each select="article">
       <xsl:if test="TEXT1 != ''">
          <xsl:call-template name="rowcount">
             <xsl:with-param name="rows" select="$rows + 1" />
          </xsl:call-template>
        </xsl:if>
   </xsl:for-each>
</xsl:template>
<xsl:template match="/kategorie">
<xsl:variable name="rows"><xsl:call-template name="rowcount"/>
/xsl:variable>
<Table aid:tcols="3" aid:trows="$rows" aid:table="table" xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/"> 

    <xsl:for-each select="artikel"> 
        <cell aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="25.30pt" aid:pstyle="abs_Produkt_Artikelnummer" aid:cstyle="zei_Produkt_Artikelnummer" aid5:cellstyle="zel_Produkt_Artikelnummer" aid:theader=""> 
            <xsl:value-of select="substring(ARTIKELNR, string-length(ARTIKELNR) - 6)"/>
        </cell> 
        <cell aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="136.76pt" aid:pstyle="abs_Produkt_Bezeichnung" aid:cstyle="zei_Produkt_Bezeichnung" aid5:cellstyle="zel_Produkt_Bezeichnung" aid:theader="">
            <xsl:value-of select="BEZEICHNUNG"/>
        </cell>
        <cell aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="21.55pt" aid:pstyle="abs_Produkt_VKBrutto" aid:cstyle="zei_Produkt_VKBrutto" aid5:cellstyle="zel_Produkt_VKBrutto" aid:theader="">
            <xsl:value-of select="substring(VK1BRUTTO, string-length(VK1BRUTTO), string-length(VK1BRUTTO)-2)"/>
        </cell>
        <xsl:variable name="freitext" select="TEXT1"/>
        <xsl:if test="$freitext != ''">
            <cell aid:table="cell" aid:crows="1" aid:ccols="1" aid:pstyle="abs__empty" aid:cstyle="zei__empty" aid5:cellstyle="zel__empty" aid:theader="">
            </cell>
            <cell aid:table="cell" aid:crows="1" aid:ccols="2" aid:pstyle="abs_Produkt_Beschreibung" aid:cstyle="zei_Produkt_Beschreibung" aid5:cellstyle="zel_Produkt_Beschreibung" aid:theader="">
                <xsl:value-of select="TEXT1"/>
            </cell>
        </xsl:if>
    </xsl:for-each> 

</Table>
</xsl:template> 
</xsl:stylesheet> 

Failures: 1. the number of rows isn't calculated correctly. 2. InDesign doesn't build a table from it's result.

Can somebody explain what's the problem and maybe give me a correct code?


Solution

  • If I am guessing correctly, you want to do something like this (non-relevant attributes omitted):

    XSLT 1.0

    <xsl:stylesheet version="1.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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
    <xsl:template match="/kategorie">
        <Table aid:tcols="3" aid:trows="{count(artikel) + count(artikel/TEXT1[text()])}"> 
            <xsl:for-each select="artikel"> 
                <cell> 
                    <xsl:value-of select="normalize-space(ARTIKELNR)"/>
                </cell> 
                <cell>
                    <xsl:value-of select="BEZEICHNUNG"/>
                </cell>
                <cell>
                    <xsl:value-of select="VK1BRUTTO"/>
                </cell>
                <xsl:if test="TEXT1/text()">
                    <cell/>
                    <cell>
                        <xsl:value-of select="TEXT1"/>
                    </cell>
                    <cell/>
                </xsl:if>
            </xsl:for-each> 
        </Table>
    </xsl:template> 
    
    </xsl:stylesheet>
    

    Applied to your input example, the result will be:

    <?xml version="1.0" encoding="UTF-8"?>
    <Table xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" xmlns:aid5="http://ns.adobe.com/AdobeInDesign/5.0/" aid:tcols="3" aid:trows="3">
       <cell>200151</cell>
       <cell>ARTIST ONE - the first release</cell>
       <cell>13,9900</cell>
       <cell>200153</cell>
       <cell>ARTIST TWO - the second release</cell>
       <cell>13,9900</cell>
       <cell/>
       <cell>Lorem ipsum dolor whatever...</cell>
       <cell/>
    </Table>