0
votes

I need to transform my XML file with XSL code in order to import the content into InDesign. Unfortunately, I'm having problems with counting child nodes of one of the groups.

Here is the XML code:

<?xml version="1.0"?>
<records>
   <list>
      <!-- SPECIAL NOTE -->
      <specialNote>
         <specialNoteTitle>Title</specialNoteTitle>
         <specialNoteContent>Special note content</specialNoteContent>
      </specialNote>
      <!-- TITLE & ADDRESS -->
      <address>
         <listTitle>December</listTitle>
         <addressLines>
            <line1>1</line1>
            <line2>2</line2>
            <line3>3</line3>
            <line4>4</line4>
         </addressLines>
      </address>
      <!-- PRODUCTS -->
      <products>
         <productNr1>
            <productCode>Jeden</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr1>
         <productNr2>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr2>
         <productNr3>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr3>
         <productNr4>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr4>
         <productNr5>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr5>
         <productNr6>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr6>
         <productNr7>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr7>
         <productNr8>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr8>
      </products>
      <!-- CODES -->
      <promoCodes>
         <promoCode1>
            <promoCode>22</promoCode>
            <instruction>22</instruction>
         </promoCode1>
         <promoCode2>
            <promoCode>21</promoCode>
            <instruction>23</instruction>
         </promoCode2>
         <promoCode3>
            <promoCode>12</promoCode>
            <instruction>12</instruction>
         </promoCode3>
         <promoCode4>
            <promoCode>22</promoCode>
            <instruction>11</instruction>
         </promoCode4>
      </promoCodes>
   </list>
   <list>
      <!-- SPECIAL NOTE -->
      <specialNote>
         <specialNoteTitle>Title</specialNoteTitle>
         <specialNoteContent>Special note content</specialNoteContent>
      </specialNote>
      <!-- TITLE & ADDRESS -->
      <address>
         <listTitle>December</listTitle>
         <addressLines>
            <line1>1</line1>
            <line2>2</line2>
            <line3>3</line3>
            <line4>4</line4>
         </addressLines>
      </address>
      <!-- PRODUCTS -->
      <products>
         <productNr1>
            <productCode>Jeden</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr1>
         <productNr2>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr2>
         <productNr3>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr3>
         <productNr4>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr4>
         <productNr5>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr5>
         <productNr6>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr6>
         <productNr7>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr7>
         <productNr8>
            <productCode>1</productCode>
            <productName>1</productName>
            <productBrand>1</productBrand>
            <productNK>1</productNK>
         </productNr8>
      </products>
      <!-- CODES -->
      <promoCodes>
         <promoCode1>
            <promoCode>22</promoCode>
            <instruction>22</instruction>
         </promoCode1>
         <promoCode2>
            <promoCode>21</promoCode>
            <instruction>23</instruction>
         </promoCode2>
         <promoCode3>
            <promoCode>12</promoCode>
            <instruction>12</instruction>
         </promoCode3>
         <promoCode4>
            <promoCode>22</promoCode>
            <instruction>11</instruction>
         </promoCode4>
      </promoCodes>
   </list>
</records>

And my XSL code:

<?xml version="1.0" encoding="UTF-8"?>
<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">

   <!-- MAIN TREE -->
   <xsl:template match="/">
      <records>
      <xsl:apply-templates/>
      </records>
   </xsl:template>

   <xsl:template match="list">
      <list>
      <xsl:apply-templates select="specialNote"/>
        <xsl:apply-templates select="address"/>
        <xsl:apply-templates select="products"/>
        <xsl:apply-templates select="promoCodes"/> 
      </list>
   </xsl:template>

   <!-- SPECIAL NOTE TEMPLATE -->
   <xsl:template match="specialNote">
      <break aid:pstyle="break">
         <xsl:if test="*">
            <table aid:table="table" aid:trows="2" aid:tcols="1">
               <cell aid:table="cell" aid5:cellstyle="special_note_title" aid:crows="1" aid:ccols="1" aid:ccolwidth="362"><xsl:value-of select="specialNoteTitle" /></cell>
               <cell aid:table="cell" aid5:cellstyle="special_note_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="362"><xsl:value-of select="specialNoteContent" /></cell>
            </table>
         </xsl:if>
      </break>
      <xsl:text>&#xa;</xsl:text>
   </xsl:template>

   <!-- ADDRESS TEMPLATE -->
   <xsl:template match="address">
      <table aid:table="table" aid:trows="4" aid:tcols="2">
         <cell aid:table="cell" aid5:cellstyle="address_title" aid:crows="4" aid:ccols="1" aid:ccolwidth="181"><xsl:value-of select="listTitle" /></cell>
         <xsl:for-each select="addressLines/*">
            <cell aid:table="cell" aid5:cellstyle="address_line" aid:crows="1" aid:ccols="1" aid:ccolwidth="181"><xsl:value-of select="." /></cell>
         </xsl:for-each>      
      </table>
      <xsl:text>&#xa;</xsl:text>
   </xsl:template>

   <!-- PRODUCTS TEMPLATE -->
   <xsl:template match="products">
      <xsl:variable name="products_number" select="count(./*)+1" />
      <table aid:table="table" aid:trows="$products_number" aid:tcols="4">
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="61">Code</cell>
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="120">Product name</cell>
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="120">Product brand</cell>
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="61">NK</cell>
         <xsl:for-each select="*">
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="61"><xsl:value-of select="productCode" /></cell>
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="120"><xsl:value-of select="productName" /></cell>
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="120"><xsl:value-of select="productBrand" /></cell>
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="61"><xsl:value-of select="productNK" /></cell>
         </xsl:for-each>      
      </table>
      <xsl:text>&#xa;</xsl:text>
   </xsl:template>

   <!-- PROMO CODES TEMPLATE -->
   <xsl:template match="promoCodes">
      <table aid:table="table" aid:trows="5" aid:tcols="2">
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="62">Codes</cell>
         <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="300">Instruction</cell>
         <xsl:for-each select="*">
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="62"><xsl:value-of select="promoCode" /></cell>
            <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="300"><xsl:value-of select="instruction" /></cell>
         </xsl:for-each>
      </table>
      <xsl:text>&#xa;</xsl:text>
   </xsl:template>

</xsl:stylesheet>

The problem can be found in products template. As you can probably see, my XML code is quite complicated. There is a lot of unique nodes like ProductNr1, ProductNr2 and so on. Unfortunately, these nodes can't be replaced by one tag (ie: "product") because the XML is exported from Excel (in my case it requires unique tag per column). In order to build InDesign's table, I need to count its rows (all children of "products" + 1). My XPATH is supposed to do that, but when I'm using it, InDesign refuses to import the XML. I assume this is because the calculated number of rows for products table isn't right.

What am I doing wrong?

2
Do you know what the output XML needs to look like in order to be accepted by the target application? If so, please edit your question and add the expected output.michael.hor257k
Right now, you are not counting unique nodes but any node. And is your issue just that $products_number renders instead of its evaluated value?Parfait
@Parfait: Yes, the problem lies with $products_number value. I tested the code with numbers instead of variables and it worked. My table will have up to 50 rows, so I'm forced to count those nodes :/yarek
But you are not counting any unique node? And is your question resolved? I am not understanding.Parfait
@Parfait: Lets assume (for a moment) that <products> is the first level of my XML structure. Its children - <ProductNr1>, <ProductNr2> and so on - are the second level. My goal is to count all of the second level elements because each of them will create a row in my table. Anything below the second level is irrelevant. Like I said before, select="count(./*)+1" provides wrong values, so I think this is the part where I'm making some mistake.yarek

2 Answers

0
votes

I can see one problem, but it might not be the only one causing the issue because I don't know what your expected XML looks like. However, the problems is with how you set the trows attribute for the table

aid:trows="$products_number"

This will literally output what you have typed, when actually you want to evaluate the variable $products_number, and use the result of the variable. To do this, use Attribute Value Templates

aid:trows="{$products_number}"

When the XML is output, it should then be output as aid:trows="9", for example.

0
votes

Tim C was quicker than me but I was about to say the same thing.

Also, you can refine your "products" search by looking at any children whose name() starts with 'productNr'

I am posting the xsl template for products for explanation:

<!-- PRODUCTS TEMPLATE -->
    <xsl:template match="products">
        <xsl:variable name="products" select="./*[starts-with(name(), 'productNr')]"/>
        <xsl:variable name="products_number" select="count($products)+1" />
        <table xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" aid:table="table" aid:trows="{$products_number}" aid:tcols="4">
            <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="61">Code</cell>
            <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="120">Product name</cell>
            <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="120">Product brand</cell>
            <cell aid:table="cell" aid5:cellstyle="table_head" aid:crows="1" aid:ccols="1" aid:ccolwidth="61">NK</cell>
            <xsl:for-each select="$products">
                <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="61"><xsl:value-of select="productCode" /></cell>
                <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="120"><xsl:value-of select="productName" /></cell>
                <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="120"><xsl:value-of select="productBrand" /></cell>
                <cell aid:table="cell" aid5:cellstyle="table_content" aid:crows="1" aid:ccols="1" aid:ccolwidth="61"><xsl:value-of select="productNK" /></cell>
            </xsl:for-each>      
        </table>
        <xsl:text>&#xa;</xsl:text>
    </xsl:template>