Hi folks, I need to use XSLT to do a few modifications to HTML when document gets saved. It all goes fine, except I got stuck on one requirement. The indent level of bulleted list may not be more than 2. So I have embedded lists:
[tt]<ul>
<li>bull0</li>
<li>bull1
<ul>
<li>bull1.1</li>
<li>here goes level 3
<ul>
<li>bull1.2.1</li>
</ul>
</li>
<li>bull1.2</li>
</ul>
</li>
</ul>[/tt]
and the task would be to move bullet points of level 3 and deeper back to level 2:
...
[tt]<li>bull1.1</li>
<li>here goes level 3</li>
<li>bull1.2.1</li>
<li>bull1.2</li>[/tt]
...
My best attempt was to use:
[tt] <xsl:template match="ul/li/ul/li/ul">
<xsl:text disable-output-escaping="yes"></li></xsl:text>
<xsl:apply-templates select="node()" />
<xsl:text disable-output-escaping="yes"><li></xsl:text>
</xsl:template>[/tt]
this removes UL tags themselves and closes the list item preceding any 3rd level UL element and opens a LI tag after, so that it produces balanced tags. Nearly OK, but 1) it produces empty tag after the embedded list and 2) it leaves trailing space in LI element preceding the removed UL tag, so that I get:
...
[tt]<li>bull1.1</li>
<li>here goes level 3
</li>
<li>bull1.2.1</li>
<li></li>
<li>bull1.2</li>[/tt]
...
It's not as bad as on the next save I will remove the empty LI tag using:
[tt] <xsl:template match="li">
<xsl:if test="node()!=''">
<xsl:element name="li">
<xsl:attribute name="class">myclass</xsl:attribute>
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:if>
</xsl:template>[/tt]
and as the users must not create the 2+ level indented lists anyway, they will have to put up with this.
Still I cannot figure out how to avoid leaving trailing space at the end of the list item preceding UL (also the text may contain other tags); and I'd prefer to handle this cleanly (without creating empty elements). Or could I process the HTML produced once more in one go in attempt to clean it up? I doubt. Any ideas?
BTW I tried to loop the preceding LI element:
[tt] <xsl:template match="ul/li/ul/li">
<xsl:for-each select="*">
...
</xsl:for-each>[/tt]
</xsl:template>
but then I loose any plain text that precedes <ul>.
[tt]<ul>
<li>bull0</li>
<li>bull1
<ul>
<li>bull1.1</li>
<li>here goes level 3
<ul>
<li>bull1.2.1</li>
</ul>
</li>
<li>bull1.2</li>
</ul>
</li>
</ul>[/tt]
and the task would be to move bullet points of level 3 and deeper back to level 2:
...
[tt]<li>bull1.1</li>
<li>here goes level 3</li>
<li>bull1.2.1</li>
<li>bull1.2</li>[/tt]
...
My best attempt was to use:
[tt] <xsl:template match="ul/li/ul/li/ul">
<xsl:text disable-output-escaping="yes"></li></xsl:text>
<xsl:apply-templates select="node()" />
<xsl:text disable-output-escaping="yes"><li></xsl:text>
</xsl:template>[/tt]
this removes UL tags themselves and closes the list item preceding any 3rd level UL element and opens a LI tag after, so that it produces balanced tags. Nearly OK, but 1) it produces empty tag after the embedded list and 2) it leaves trailing space in LI element preceding the removed UL tag, so that I get:
...
[tt]<li>bull1.1</li>
<li>here goes level 3
</li>
<li>bull1.2.1</li>
<li></li>
<li>bull1.2</li>[/tt]
...
It's not as bad as on the next save I will remove the empty LI tag using:
[tt] <xsl:template match="li">
<xsl:if test="node()!=''">
<xsl:element name="li">
<xsl:attribute name="class">myclass</xsl:attribute>
<xsl:apply-templates select="node()" />
</xsl:element>
</xsl:if>
</xsl:template>[/tt]
and as the users must not create the 2+ level indented lists anyway, they will have to put up with this.
Still I cannot figure out how to avoid leaving trailing space at the end of the list item preceding UL (also the text may contain other tags); and I'd prefer to handle this cleanly (without creating empty elements). Or could I process the HTML produced once more in one go in attempt to clean it up? I doubt. Any ideas?
BTW I tried to loop the preceding LI element:
[tt] <xsl:template match="ul/li/ul/li">
<xsl:for-each select="*">
...
</xsl:for-each>[/tt]
</xsl:template>
but then I loose any plain text that precedes <ul>.