Reputation: 834
I've the below piece of XML.
<section level="sect2" number-type="manual">
<para align="center">
<phrase>24-2</phrase>
<content-style font-style="italic">Destroying [or Damaging] property, contrary to section 60(1) of the Crimes Ordinance Cap 200, Laws of Hong Kong.</content-style>
</para>
</section>
and when i apply the below XSLT
<xsl:template name="para" match="section/para">
<xsl:choose>
<xsl:when test="current()/@align=center and ./@differentiation">
<div class="para align-{@align}">
<xsl:apply-templates/>
</div>
</xsl:when>
<xsl:when test="current()/@align=center and not(./@differentiation)">
<div class="para align1-{@align}">
<xsl:apply-templates/>
</div>
</xsl:when>
<xsl:when test="current()/@align and ./phrase[1]">
<div class="para new">
<xsl:apply-templates/>
</div>
</xsl:when>
<xsl:when test="current()/@align">
<div class="para align-{@align}">
<xsl:apply-templates/>
</div>
</xsl:when>
<xsl:otherwise>
<div class="para">
<xsl:apply-templates/>
</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()">
<xsl:analyze-string select="." regex="(([Cc]hapter)\s(\d+))">
<xsl:matching-substring>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="([0-9]+)\.([0-9]+)">
<xsl:matching-substring>
<xsl:variable name="num">
<xsl:value-of select="string-length(regex-group(2))"/>
</xsl:variable>
<a
href="{concat('er:#ABHK_CH_',format-number(number(regex-group(2)),'00'),'/P',format-number(number(regex-group(2)),'0'),'-',regex-group(3))}">
<xsl:value-of select="."/>
</a>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template name="phrase" match="phrase">
<xsl:variable name="phrl">
<xsl:value-of select="string-length(text())"/>
</xsl:variable>
<xsl:variable name="phrase">
<xsl:value-of select="concat('P',text())"/>
</xsl:variable>
<xsl:variable name="newphrase" select="translate($phrase,'.','-')"/>
<a>
<xsl:attribute name="name">
<xsl:value-of select="$newphrase">
</xsl:value-of>
</xsl:attribute>
</a>
<xsl:choose>
<xsl:when test="../@align">
<span class="phrase">
<xsl:value-of select="current()"/>
</span>
<span class="align-center">
<xsl:apply-templates select="following-sibling::node()[1]"/>
</span>
</xsl:when>
<xsl:when test="$phrl=3">
<span class="phrase">
<xsl:value-of select="current()"/>
</span>
<xsl:text disable-output-escaping="yes">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;</xsl:text>
</xsl:when>
<xsl:when test="$phrl=4">
<span class="phrase">
<xsl:value-of select="current()"/>
</span>
<xsl:text disable-output-escaping="yes">&#160;&#160;&#160;&#160;</xsl:text>
</xsl:when>
<xsl:otherwise>
<span class="phrase">
<xsl:value-of select="current()"/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="content-style">
<xsl:choose>
<xsl:when test="./@format">
<span class="{concat('format-',@format)}">
<xsl:apply-templates/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',@font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:choose>
<xsl:when test="../@align">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
<xsl:apply-templates select="para"/>
</xsl:otherwise>
</xsl:choose>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
the output i get is
24-2 Destroying [or Damaging] property, contrary to section 60(1) of the Crimes Ordinance Cap 200, Laws of Hong Kong. Destroying [or Damaging] property, contrary to section 60(1) of the Crimes Ordinance Cap 200, Laws of Hong Kong.
here Destroying [or Damaging] property, contrary to section 60(1) of the Crimes Ordinance Cap 200, Laws of Hong Kong.
is getting repeated though the template is called once. please let me know where am i going wrong.
Thanks
Upvotes: 0
Views: 54
Reputation: 70648
Within the template that matches the para element you are doing this
<xsl:apply-templates/>
This will look at both the child nodes of the para element and select templates that match them. As one of the child elements is content-style this will obviously apply the template that matches it.
However, within the template that matches phrase (which is the other child of para you do this (in the case where the para element has an align attribute, which is does here)
<xsl:apply-templates select="following-sibling::node()[1]"/>
The following sibling is the content-style, and so this will also use the template. Thus the template matching content-style gets called twice.
One solution is to the template matching para so that instead of doing <xsl:apply-templates/>
, it explicitly ignores nodes that following phrase elements
<xsl:apply-templates select="*[not(preceding-sibling::*[1][local-name()='phrase'])]" />
Try this template for para instead
<xsl:template name="para" match="section/para">
<xsl:choose>
<xsl:when test="current()/@align=center and ./@differentiation">
<div class="para align-{@align}">
<xsl:apply-templates select="*[not(preceding-sibling::*[1][local-name()='phrase'])]" />
</div>
</xsl:when>
<xsl:when test="current()/@align=center and not(./@differentiation)">
<div class="para align1-{@align}">
<xsl:apply-templates select="*[not(preceding-sibling::*[1][local-name()='phrase'])]" />
</div>
</xsl:when>
<xsl:when test="current()/@align and ./phrase[1]">
<div class="para new">
<xsl:apply-templates select="*[not(preceding-sibling::*[1][local-name()='phrase'])]" />
</div>
</xsl:when>
<xsl:when test="current()/@align">
<div class="para align-{@align}">
<xsl:apply-templates select="*[not(preceding-sibling::*[1][local-name()='phrase'])]" />
</div>
</xsl:when>
<xsl:otherwise>
<div class="para">
<xsl:apply-templates/>
</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Upvotes: 1