The following is some simple XML with a multilevel unordered list that I would like to import into Adobe InDesign:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<STORY>
<Headline>XML test</Headline>
<Standfirst><p>Standfirst</p></Standfirst>
<Story_text>
<h1>Heading 1</h1>
<p>para text</p>
<ul>
<li>
level 1
<ul>
<li>
level 2
<ul>
<li>
level 3
<ul>
<li>
level 4
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
level 1
<ul>
<li>
level 2
</li>
</ul>
</li>
<li>
level 1
</li>
</ul>
</Story_text>
</STORY>
InDesign allows you to map its paragraph styles to XML tags. (e.g. <h1>
can be assigned to my Header 1 paragraph style). This is fine for the most part; however, my problem arises with multilevel/nested bulleted lists.
To do multi-level bullets in InDesign, I have separate paragraph styles for each level of bullets. Below is how I'd like the unordered list to appear in InDesign, with the relevant paragraph styles in brackets.
The problem is InDesign has no way of distinguishing between multilevel bullets. As you would expect, if I assign <li>
to one of the bullet paragraph styles, all the bullets will become that level, same if I assign the style to <ul>
.
I would like to use XSLT to output the following:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<STORY>
<Headline>XML test</Headline>
<Standfirst><p>Standfirst</p></Standfirst>
<Story_text>
<h1>Heading 1</h1>
<p>para text</p>
<ul>
<li1>
level 1
<ul>
<li2>
level 2
<ul>
<li3>
level 3
<ul>
<li4>
level 4
</li4>
</ul>
</li3>
</ul>
</li2>
</ul>
</li1>
<li1>
level 1
<ul>
<li2>
level 2
</li2>
</ul>
</li1>
<li1>
level 1
</li1>
</ul>
</Story_text>
</STORY>
This will allow me to map the bullet level to the appropriate paragraph style in InDesign (e.g. <li1>
can be mapped to TEXT: bullet 1, <li2>
mapped to TEXT: bullet 2 and so on). I am quite new to XML and XSLT, so any help would be massively appreciated.
You should first start off with the XSLT identity template to copy all elements across unchanged...
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
Then all you need is to add an overriding template that matches li
and outputs a new element with the number of ancestors in the name instead.
<xsl:template match="li">
<xsl:element name="li{count(ancestor::li) + 1}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
Note the curly braces indicate an Attribute Value Template, which indicate an expression to be evaluated, rather than output literally.
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="no" />
<xsl:template match="li">
<xsl:element name="li{count(ancestor::li) + 1}">
<xsl:apply-templates select="@*|node()"/>
</xsl:element>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>