I've the below XML.
<section level="sect1">
<title num="1.3"><content-style font-style="bold">Common Breaches</content-style></title>
<page num="9"/>
<section level="sect2">
<title><content-style font-style="bolditalic">Non-payment of Rent/Service Charge/Hiring Charge/Licence Fee</content-style></title>
<orderedlist type="manual">
<item num="1.3.1"><para>The most common breach in a Tenancy Agreement is the late payment or non payment of rent. The Tenancy Agreement usually provides for the right of the Landlord to re-enter the premises and determine the tenancy upon non-payment of rent for a period of time. This is in addition to the Landlord's rights to sue the Tenant for any outstanding rent and any monies owing under the tenancy up to the expiry of the tenancy and forfeit the security deposit.</para></item>
<item num="1.3.2"><para>The Landlord may commence what are known as Writ of Distress proceedings or Writ of Summons proceedings to claim for the unpaid rent. The Writ of Distress is the more effective remedy, however only rent may be recovered under the Writ of Distress.</para></item>
</orderedlist>
</section>
and i'm using the below XSLT.
<xsl:template name="section" match="section">
<!-- Variables-->
<xsl:variable name="classname">
<!--Get name attribute of current node -->
<xsl:value-of select="concat('section-',#level)"/>
</xsl:variable>
<xsl:variable name="size">
<xsl:value-of select="string-length(ancestor::chapter[1]/#num)"/>
</xsl:variable>
<xsl:variable name="Chn">
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:choose>
<xsl:when test="$size=1">
<xsl:value-of select="concat('0',$Chn)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Chn"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="sectnum">
<xsl:number level="any" count="section" format="1"/>
</xsl:variable>
<!--Create a string variable by concat string method -->
<xsl:variable name="sectionname">
<xsl:value-of select="concat('CH_',$chapternumber,'-SEC-', $sectnum)"/>
</xsl:variable>
<!-- Template Content -->
<xsl:if test="./page[1]">
<xsl:apply-templates select="./page[1]"/>
</xsl:if>
<div class="{$classname}">
<a name="{$sectionname}"> </a>
<div class="section-title">
<xsl:if test="not(contains(./#num,'unnumbered'))">
<xsl:if test="./title/#num">
<span class="section-num">
<a name="{concat('P',translate(./title/#num,'.','-'))}"></a>
<xsl:value-of select="./title/#num"/>
</span>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:if>
<xsl:apply-templates select="./title/child::node()[fn:not(self::page)]"/>
</div>
<!--<xsl:apply-templates select="child::node()[not(self::title)]"/>-->
</div>
</xsl:template>
<xsl:template name="para" match="section/para">
<xsl:choose>
<xsl:when test="current()/#align">
<div class="para align-{#align}">
<xsl:apply-templates/>
</div>
</xsl:when>
<xsl:when test="current()/#num">
<xsl:choose>
<xsl:when test="child::node()[1][self::*]">
<xsl:apply-templates select="child::page[1]"/>
<div class="para">
<xsl:call-template name="phrase"/>
<xsl:apply-templates select="child::node()[not(self::page)]"/>
</div>
</xsl:when>
<xsl:otherwise>
<div class="para">
<xsl:call-template name="phrase"/>
<xsl:apply-templates/>
</div>
</xsl:otherwise>
</xsl:choose>
</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:choose>
<xsl:when test="number(regex-group(3)) < number(9)">
<a href="{concat('er:#MCCL_CH_',format-number(number(regex-group(3)),'00'),'/','MCCL_CH_',format-number(number(regex-group(3)),'00'))}">
<xsl:value-of select="."/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="[Pp]aragraphs\s([0-9]+)\.([0-9]+)\sand\s([0-9]+)\.([0-9]+)">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="number(regex-group(1)) < number(9)">
<a
href="{concat('er:#MCCL_CH_',format-number(number(regex-group(1)),'00'),'/P',format-number(number(regex-group(1)),'0'),'-',format-number(number(regex-group(2)),'000'))}">
<xsl:value-of select="substring-before(., ' and')"/>
</a>
<xsl:text> and </xsl:text>
<a
href="{concat('er:#MCCL_CH_',format-number(number(regex-group(3)),'00'),'/P',format-number(number(regex-group(3)),'0'),'-',format-number(number(regex-group(4)),'000'))}">
<xsl:value-of select="substring-after(., 'and ')"/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="[Pp]aragraph\s([0-9]+)\.([0-9]+)">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="number(regex-group(1)) < number(9)">
<a
href="{concat('er:#MCCL_CH_',format-number(number(regex-group(1)),'00'),'/P',format-number(number(regex-group(1)),'0'),'-',format-number(number(regex-group(2)),'000'))}">
<xsl:value-of select="."></xsl:value-of>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="http://[^ ]+">
<xsl:matching-substring>
<a href="{.}">
<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:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template name="orderedlist" match="orderedlist">
<ol class="eng-orderedlist orderedlist">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template name="orderitem" match="item">
<xsl:choose>
<xsl:when test="not(ends-with(#num, '.')) and fn:contains(#num,'.')">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<li class="item">
<xsl:apply-templates/>
</li>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="orderitempara" match="item/para">
<xsl:choose>
<xsl:when test="contains(../../#type,'manual')">
<div class="para">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:choose>
<xsl:when test="contains(parent::item[1]/#num,'bull')">
<xsl:text>•</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="not(ends-with(../#num, '.')) and fn:contains(../#num,'.')">
<xsl:call-template name="phrase"/>
</xsl:when>
<xsl:when test="../#num">
<span class="item-num">
<xsl:apply-templates select="parent::item[1]/#num"/>
</span>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</div>
</xsl:when>
<xsl:otherwise>
<span class="bullet-list">
<xsl:value-of select="../../#type"/>
</span>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="page">
<xsl:processing-instruction name="pb">
<xsl:text>label='</xsl:text>
<xsl:value-of select="./#num"/>
<xsl:text>'</xsl:text>
<xsl:text>?</xsl:text>
</xsl:processing-instruction>
<a name="{concat('pg_',./#num)}"/>
<xsl:apply-templates/>
</xsl:template>
<xsl:template name="phrase">
<xsl:choose>
<xsl:when test="parent::title">
<xsl:variable name="phrase">
<xsl:value-of select="concat('P',#num)"/>
</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>
<span class="phrase1">
<xsl:value-of select="current()"/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="phrase">
<xsl:value-of select="concat('P',../#num)"/>
</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>
<span class="phrase">
<xsl:value-of select="../#num"/>
</span>
</xsl:otherwise>
</xsl:choose>
<!--<xsl:apply-templates/>-->
</xsl:template>
when i run this i'm getting output as below.
here the processing instruction number 9 (pb label='9') is getting duplicated, please let me know how can i get the below output.
Thanks
have your page template in a different mode
<xsl:apply-templates select="page[1]" mode="insert_page"/>
and
<xsl:template match="page" mode="insert_page">
Related
I've the below XML.
<toc-item>
<toc-title>
6A. <content-style font-style="italic">(Repealed 64 of 1989 s.9)
</content-style>
</toc-title>
<toc-pg>U2/6A</toc-pg>
</toc-item>
and i'm running with the below XSLT.
<xsl:template name="toc" match="toc">
<div class="toc">
<div class="toc-part">
<table class="toc-div">
<tbody>
<tr>
<td>
<xsl:for-each select="toc-part/toc-div/toc-item">
<xsl:call-template name="toc-item"/>
</xsl:for-each>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</xsl:template>
<xsl:template name="toc-item" match="toc-item">
<xsl:variable name="tocpg">
<xsl:value-of select="concat('P',normalize-space(current()/toc-pg/text()))"/>
</xsl:variable>
<xsl:variable name="tocpgtag">
<xsl:choose>
<xsl:when test="contains($tocpg,'.')">
<xsl:value-of select="translate($tocpg,'.', '-')"/>
</xsl:when>
<xsl:when test="contains($tocpg,'/')">
<xsl:value-of select="translate($tocpg,'/', '-')"/>
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="nu">
<xsl:number format="I."/>
</xsl:variable>
<xsl:variable name="Brac">
<xsl:call-template name="get_number_type">
<xsl:with-param name="number_string" select="./#num"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="NewL">
<xsl:value-of select="normalize-space($chapternumber)"/>
</xsl:variable>
<xsl:variable name="size">
<xsl:value-of select="fn:string-length($NewL)"/>
</xsl:variable>
<xsl:variable name="newNum">
<xsl:choose>
<xsl:when test="$size=1">
<xsl:value-of select="concat('0',normalize-space($NewL))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="normalize-space($NewL)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="d">
<xsl:value-of select="concat('toc-item-',$ThisDocument//ntw:nums[#num=1]/#word,'-level')"/>
</xsl:variable>
<xsl:variable name="new">
<xsl:value-of select="concat('er:#HKWBV1_ORD_',$newNum,'/',$tocpgtag)"/>
</xsl:variable>
<table class="toc-item-first-level">
<tbody>
<tr>
<xsl:choose>
<xsl:when test="./toc-pg">
<xsl:choose>
<xsl:when test="fn:contains(./toc-title,'.')">
<td class="toc-item-num">
<xsl:value-of select="concat(substring-before(./toc-title,'.'),'.')"/>
</td>
</xsl:when>
<xsl:otherwise>
<td colspan="2" align="left" class="padtit">
<xsl:value-of select="./toc-title"/>
</td>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="fn:contains(./toc-title,'.')">
<td class="toc-title">
<xsl:apply-templates select="./toc-title" mode="x"/>
</td>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
<td class="toc-pg">
<xsl:choose>
<xsl:when test="contains(./toc-pg,'.')">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</xsl:when>
<xsl:when test="contains(./toc-pg,'/')">
<a href="{$new}">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</a>
</xsl:when>
<xsl:otherwise>
<a href="{concat('#pg_',toc-pg)}">
<xsl:value-of select="normalize-space(current()/toc-pg)"/>
</a>
</xsl:otherwise>
</xsl:choose>
</td>
</xsl:when>
<xsl:otherwise>
<td align="center" colspan="3">
<span class="font-style-bold">
<xsl:apply-templates select="./toc-title"/>
</span>
</td>
</xsl:otherwise>
</xsl:choose>
</tr>
</tbody>
</table>
<!--</table>-->
</xsl:template>
<xsl:template match="toc-title/text()" mode="x">
<xsl:analyze-string select="substring-after(.,'.')" regex="(\w)">
<xsl:matching-substring>
<xsl:apply-templates select="regex-group(1)"/>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
here what i'm trying to achieve is in my XML in toc-title, there is a number followed by content-style, here my output is having 2 <td>
the number before .
Content after .
if there is no other tag except text after ., i'm able to get the text correctly, and i want to apply-templates for the content after ., please let me know how i can get this done.
here is the demo
Thanks
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">        </xsl:text>
</xsl:when>
<xsl:when test="$phrl=4">
<span class="phrase">
<xsl:value-of select="current()"/>
</span>
<xsl:text disable-output-escaping="yes">    </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
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>
Hi i'm having the below xml.
<primaryie>
<content-style font-style="bold">Administration</content-style>
</primaryie>
and when i'm applying the below xslt it is working fine.(the content-style part)
<xsl:template match="primaryie">
<div class="primaryie">
<xsl:apply-templates select="content-style"/>
<xsl:if test="contains(current()/text(), '.')">
<xsl:variable name="numberString" select="substring(current()/text(), string-length(substring-before(current()/text(),'.'))-1)"></xsl:variable>
<xsl:call-template name="numbersToLink">
<xsl:with-param name="numbersString" select="$numberString"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</div>
</xsl:template>
<xsl:template name="numbersToLink">
<xsl:param name="numbersString"></xsl:param>
<xsl:choose>
<xsl:when test="contains($numbersString, ',')">
<xsl:call-template name="splitByComma">
<xsl:with-param name="numString" select="$numbersString"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($numbersString, '-')">
<xsl:call-template name="splitByHyphen">
<xsl:with-param name="numString" select="$numbersString"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="5 >= string-length(normalize-space($numbersString))">
<xsl:variable name="x">
<xsl:value-of select="substring-after($numbersString,'.')"></xsl:value-of>
</xsl:variable>
<xsl:variable name="y">
<xsl:value-of select="normalize-space(substring-before($numbersString,'.'))"></xsl:value-of>
</xsl:variable>
<xsl:variable name="conca">
<xsl:value-of select="concat('er:#BVI_CH_0',$y,'/P',$y,'-',$x)"/>
</xsl:variable>
<a href="{$conca}">
<xsl:value-of select="$numbersString"/>
</a>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="splitByComma">
<xsl:param name="numString"></xsl:param>
<xsl:choose>
<xsl:when test="contains(substring-before($numString,','), '-')">
<xsl:call-template name="splitByHyphen">
<xsl:with-param name="numString" select="$numString"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($numString,',')">
<xsl:variable name="abc">
<xsl:value-of select="normalize-space(substring-before($numString,'.'))"/>
</xsl:variable>
<xsl:variable name="def">
<xsl:value-of select="substring-before(substring-after($numString,'.'),',') "/>
</xsl:variable>
<xsl:variable name="conct">
<xsl:value-of select="concat('er:#BVI_CH_0',$abc,'/P',$abc,'-',$def)"/>
<!--"concat(concat('er:#BVI_CH_0',,'/P',$y,'-',$x)"/-->
</xsl:variable>
<a href="{$conct}">
<xsl:value-of select="substring-before($numString,',')"/>
</a>
<xsl:text>, </xsl:text>
<xsl:if test="contains(substring-after($numString,','), '.')">
<xsl:call-template name="numbersToLink">
<xsl:with-param name="numbersString" select="normalize-space(substring-after($numString,','))"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="splitByHyphen">
<xsl:param name="numString"></xsl:param>
<xsl:choose>
<xsl:when test="contains($numString,'-')">
<xsl:variable name="abc">
<xsl:value-of select="normalize-space(substring-before($numString,'.'))"/>
</xsl:variable>
<xsl:variable name="def">
<xsl:value-of select="substring-before(substring-after($numString,'.'),'-') "/>
</xsl:variable>
<xsl:variable name="conct">
<xsl:value-of select="concat('er:#BVI_CH_0',$abc,'/P',$abc,'-',$def)"/>
<!--"concat(concat('er:#BVI_CH_0',,'/P',$y,'-',$x)"/-->
</xsl:variable>
<a href="{$conct}">
<!--<xsl:value-of select="substring-before($numString,'-')"/>-->
<xsl:value-of select="substring-before($numString,'-')"/>
</a>
<xsl:text>–</xsl:text>
<xsl:if test="contains(substring-after($numString,'-'), '.')">
<xsl:call-template name="numbersToLink">
<xsl:with-param name="numbersString" select="normalize-space(substring-after($numString,'-'))"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
but i have a special case in the same document as below xml states.
<primaryie>
<content-style font-style="bold">VIRRGIN system</content-style> 7.204, 7.205
</primaryie>
here when i'm applying the above template it is working with content-style, but i want it to work also with numberstolink template.
the outputs are as below.
current:
<div class="primaryie"><span class="font-style-bold">Virgin Islands Special Trust Act (VISTA) 9.077</span></div>
expexted:
<div class="primaryie"><span class="font-style-bold">Virgin Islands Special Trust Act (VISTA) 9.077</span></div>
Please change this below portion in your code
<xsl:template match="primaryie">
<div class="primaryie">
<xsl:apply-templates select="content-style"/>
<xsl:if test="contains(current(), '.')">
<xsl:variable name="numberString" select="substring(current(), string-length(substring-before(current(),'.'))-1)"></xsl:variable>
<xsl:call-template name="numbersToLink">
<xsl:with-param name="numbersString" select="$numberString"></xsl:with-param>
</xsl:call-template>
</xsl:if>
</div>
</xsl:template>
Use only Current() instead of Current()/Text()
Output for give XML is
<div class="primaryie">VIRRGIN system 7.204, 7.205</div>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes" />
<xsl:strip-space elements="*" />
<!-- <xsl:template match="//edx:rule" xmlns:edx="http://www.cisco.com/BRL">
<xsl:apply-templates />
</xsl:template> -->
<xsl:template match="*">
<xsl:element name="{local-name(.)}">
<xsl:apply-templates select="#* | node()" />
</xsl:element>
</xsl:template>
<xsl:template match="lhs" name="lhsTemplate">
<xsl:element name="lhs">
<xsl:choose>
<xsl:when test="incident != ''">
<xsl:for-each select="incident">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<!-- <xsl:call-template name = "incidentTemplate"/> -->
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="evaluate != ''">
<xsl:for-each select="evaluate">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<!-- <xsl:call-template name = "evaluateTemplate"/> -->
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="ruleReference != ''">
<xsl:value-of select="ruleReference" />
</xsl:when>
<xsl:otherwise>
<xsl:text> no elements encountered in lhs block</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<xsl:template match="rhs" name="rhsTemplate">
<xsl:element name="rhs">
<xsl:choose>
<xsl:when test="modify != ''">
<xsl:for-each select="modify">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:when test="tryCatchBlock/try/callFunction != ''">
<xsl:for-each select="tryCatchBlock/try/callFunction">
<xsl:element name="freeForm">
<xsl:element name="text">
<xsl:apply-templates select="." />
<xsl:text>;</xsl:text>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:text> no elements encountered in Try block</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
<!-- FIELE VALUES TEMPLATE -->
<xsl:template match="fieldValues" name="fieldValuesTemplate">
<xsl:for-each select="fieldValue" >
<!-- <xsl:if test="field!=''">
<xsl:value-of select="field"/>
<xsl:text>=</xsl:text>
</xsl:if> -->
<xsl:choose>
<xsl:when test="value/literal !=''">
<xsl:value-of select="value/literal"/>
</xsl:when>
<xsl:when test="value/formula !=''">
<xsl:apply-templates select="value/formula"/>
</xsl:when>
<xsl:when test="value/callMethodOnBoundVariable != ''">
<xsl:apply-templates select="value/callMethodOnBoundVariable"/>
</xsl:when>
<xsl:when test="value/callApi !=''">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:when test="value/boundVariable !=''">
<xsl:value-of select="value/boundVariable"/>
</xsl:when>
<xsl:when test="value/enum != ''">
<xsl:value-of select="value/enum"/>
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content"/>
</xsl:when>
<xsl:otherwise>
<xsl:text>No values encountered inside field</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- INSERT LOGICAL TEMPLATE -->
<xsl:template match="insertLogical" name="insertLogicalTemplate">
<xsl:value-of select="factType"/>
<xsl:text> </xsl:text>
<xsl:value-of select="boundName"/>
<xsl:text> = new </xsl:text>
<xsl:value-of select="factType"/>
<xsl:text>(</xsl:text>
<xsl:if test="fieldValues!=''">
<xsl:apply-templates select="fieldValues"/>
</xsl:if>
<xsl:text>);</xsl:text>
<xsl:text>insertLogical</xsl:text>
<xsl:text>(</xsl:text>
<xsl:value-of select="boundName"/>
<xsl:text>);</xsl:text>
</xsl:template>
<!-- END OF THE INSERT LOGICAL TEMPLATE -->
<!-- ASSERT MODIFY TEMPLATE -->
<xsl:template match="modify" name="modifyTemplate">
<xsl:text>modify</xsl:text>
<xsl:text>( </xsl:text>
<xsl:value-of select="variable"/>
<xsl:text> ){ </xsl:text>
<xsl:if test="fieldValues!=''">
<xsl:apply-templates select="fieldValues"/>
</xsl:if>
<xsl:text> };</xsl:text>
</xsl:template>
<!-- END OF THE MODIFY TEMPLATE -->
<!-- RETRACT TEMPLATE -->
<xsl:template match="retract" name="retractTemplate">
<xsl:text>retract(</xsl:text>
<xsl:value-of select="."/>
<xsl:text>);</xsl:text>
</xsl:template>
<!-- END OF THE RETRACT TEMPLATE -->
<!-- start leftOperandTemplate -->
<xsl:template match="leftOperand" name="leftOperandTemplate">
<xsl:choose>
<xsl:when test="field/fieldName != ''">
<xsl:value-of select="field/fieldName" />
</xsl:when>
<xsl:when test="boundVariable/variableName != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:when test="expression != ''">
<xsl:apply-templates select="expression" /> <!-- TO DO -->
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="literal" />
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="callFunction != ''">
<xsl:apply-templates select="callFunction" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No left operands found!</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- end leftOperandTemplate -->
<!-- start Right operand template -->
<xsl:template match="rightOperand" name="rightOperandTemplate">
<xsl:choose>
<xsl:when test="boundVariable/variableName != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:when test="configurableVariable/variableName != ''">
<xsl:value-of select="configurableVariable/variableName" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="literal" />
</xsl:when>
<xsl:when test="value/content != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="callFunction != ''">
<xsl:apply-templates select="callFunction" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="expression != ''">
<xsl:apply-templates select="expression" /> <!-- TO DO -->
</xsl:when>
<xsl:otherwise>
<xsl:text>No right operands found!</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- end Right operand template -->
<!-- start Comparison operator template -->
<xsl:template match=" operator | comparisonOperator" name="compareOperatorTemplate">
<xsl:choose>
<xsl:when test=".='gt'">
<xsl:value-of select="' > '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'lt'">
<xsl:value-of select="' < '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=".='eq'">
<xsl:value-of select="' == '" disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'ne'">
<xsl:value-of select="' != '" disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'lt or eq'">
<xsl:value-of select="' <= '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'gt or eq'">
<xsl:value-of select="' >= '"
disable-output-escaping="yes" />
</xsl:when>
<xsl:when test=". = 'matches'">
<xsl:value-of select="' matches '" />
</xsl:when>
<xsl:when test=". = 'not matches'">
<xsl:value-of select="' not matches '" />
</xsl:when>
<xsl:when test=". = 'contains'">
<xsl:value-of select="' contains '" />
</xsl:when>
<xsl:when test=". = 'not contains'">
<xsl:value-of select="' not contains '" />
</xsl:when>
<xsl:when test=". = 'memberOf'">
<xsl:value-of select="' memberOf '" />
</xsl:when>
<xsl:when test=". = 'not memberOf'">
<xsl:value-of select="' not memberOf '" />
</xsl:when>
<xsl:when test=". = 'sounds like'">
<xsl:value-of select="' sounds like '" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No operator found</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- End Comparison operator template -->
<xsl:template match="evaluate" name="evaluateTemplate">
<xsl:text disable-output-escaping="yes">eval(</xsl:text>
<xsl:if test=". !=''">
<xsl:apply-templates select="leftOperand" />
<xsl:if test="comparisonOperator !=''">
<xsl:apply-templates select="comparisonOperator" />
</xsl:if>
<xsl:apply-templates select="rightOperand" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:template>
<!-- END EVALUATE TEMPLATE -->
<!-- start CALL FUNCTION TEMPLATE -->
<xsl:template match="callFunction" name="callFunctionTemplate">
<xsl:if test=". !=''">
<xsl:if test="returnType!='' and returnTypeBoundName !='' ">
<xsl:value-of select="returnType" />
<xsl:text> </xsl:text>
<xsl:value-of select="returnTypeBoundName" />
<xsl:text>=</xsl:text>
</xsl:if>
<xsl:if test="functionName!=''">
<xsl:value-of select="functionName" />
<xsl:text>(</xsl:text>
<!-- <xsl:apply-templates select="args"/> -->
<xsl:call-template name="argsTemplate" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:template>
<!-- END OF THE CALL FUNCTION TEMPLATE -->
<!-- START ARGS TEMPLATE -->
<xsl:template match="args" name="argsTemplate">
<xsl:if test="args/arg != ''">
<xsl:for-each select="args/arg">
<xsl:choose>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="value != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:value-of select="." />
</xsl:when>
<xsl:when test="boundVariable != ''">
<xsl:value-of select="boundVariable/variableName" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No Args</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- END OF THE ARGS TEMPLATE -->
<!-- START of the Call Method on Bound Variable function -->
<xsl:template match="callMethodOnBoundVariable" name="callMethodOnBoundVariableTemplate">
<xsl:value-of select="boundVariableName" />
<xsl:text>.</xsl:text>
<xsl:value-of select="methodName" />
<xsl:text>(</xsl:text>
<!-- <xsl:value-of select="params/param/boundVariable" /> -->
<xsl:call-template name="paramsTemplate" />
<xsl:text>)</xsl:text>
</xsl:template>
<!-- End of the Call Method on Bound Variable function -->
<!-- START CALL API TEMPLATE -->
<xsl:template match="callApi" name="callApiTemplate">
<!-- <xsl:if test="returnType != 'void'"> <xsl:value-of select="returnType
" /> <xsl:text> </xsl:text> </xsl:if> -->
<xsl:value-of select="boundVaribleName" />
<xsl:if test="boundVaribleName[.!='']">
<xsl:text>=</xsl:text>
</xsl:if>
<xsl:value-of select="serviceVariableName" />
<xsl:text>.</xsl:text>
<xsl:value-of select="methodName" />
<xsl:text>(</xsl:text>
<xsl:call-template name="paramsTemplate" />
<xsl:text>)</xsl:text>
</xsl:template>
<!-- END call API TEMPLATE -->
<!-- FORMULA TEMPLATE -->
<xsl:template match="formula" name="formulaTemplate">
<xsl:if test="'leftOperand'">
<xsl:call-template name="formulaWithoutPeranthesisTemplate" />
</xsl:if>
<xsl:if test="'peranthesis'">
<xsl:call-template name="formulaWithPeranthesisTemplate" />
</xsl:if>
</xsl:template>
<!-- END OF THE FORMULA TEMPLATE -->
<!-- start Formula without peranthesis template -->
<xsl:template match="formulaWithoutPeranthesis" name="formulaWithoutPeranthesisTemplate">
<xsl:if test="leftOperand">
<xsl:apply-templates select="leftOperand" />
</xsl:if>
<xsl:if test="arithmeticOperator">
<xsl:apply-templates select="arithmeticOperator" />
</xsl:if>
<xsl:if test="rightOperand">
<xsl:apply-templates select="rightOperand" />
</xsl:if>
</xsl:template>
<!-- End Formula without peranthesis template -->
<!-- start Formula withparenthesis template -->
<xsl:template match="formulaWithPeranthesis" name="formulaWithPeranthesisTemplate">
<xsl:if test="peranthesis != ''">
<xsl:text>(</xsl:text>
<xsl:if test="peranthesis/leftOperand !=''">
<xsl:apply-templates select="peranthesis/leftOperand" />
</xsl:if>
<xsl:if test="peranthesis/arithmeticOperator">
<xsl:apply-templates select="peranthesis/arithmeticOperator" />
</xsl:if>
<xsl:if test="peranthesis/rightOperand">
<xsl:apply-templates select="peranthesis/rightOperand" />
</xsl:if>
<xsl:text>)</xsl:text>
</xsl:if>
</xsl:template>
<!-- END Formula with parenthesis template -->
<!-- START ARITHMETIC OPERATOR -->
<xsl:template match="arithmeticOperator" name="arithmeticOperatorTemplate">
<xsl:choose>
<xsl:when test="'+'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'-'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'*'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'/'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:when test="'%'">
<xsl:value-of select=" . " />
</xsl:when>
<xsl:otherwise>
<xsl:text>Not a valid airthmetic operator</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- END ARITHMETIC OPERATOR -->
<!-- START OF THE PARAMS TEMPLATE -->
<xsl:template match="params" name="paramsTemplate">
<xsl:if test="params/param != ''">
<xsl:for-each select="params/param">
<xsl:choose>
<xsl:when test="callMethodOnBoundVariable != ''">
<xsl:apply-templates select="callMethodOnBoundVariable" />
</xsl:when>
<xsl:when test="formula != ''">
<xsl:apply-templates select="formula" />
</xsl:when>
<xsl:when test="callApi != ''">
<xsl:apply-templates select="callApi" />
</xsl:when>
<xsl:when test="value != ''">
<xsl:value-of select="value/content" />
</xsl:when>
<xsl:when test="literal != ''">
<xsl:text>"</xsl:text>
<xsl:value-of select="." />
<xsl:text>"</xsl:text>
</xsl:when>
<xsl:when test="boundVariable != ''">
<xsl:value-of select="boundVariable" />
</xsl:when>
<xsl:when test="enum != ''">
<xsl:value-of select="enum" />
</xsl:when>
<xsl:otherwise>
<xsl:text>No Param</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:if>
</xsl:template>
<!-- END OF THE PARAMS TEMPLATE -->
<!--START COMPOSITE PATTERN TEMPLATE -->
<xsl:template match='compositePattern' name="compositePatternTemplate">
<xsl:if test="type != ''">
<xsl:value-of select="type" />
<xsl:text> </xsl:text>
</xsl:if>
<xsl:apply-templates select="patterns" />
</xsl:template>
<!-- END COMPOSITE PATTERN TEMPLATE -->
<xsl:template name="tagAndContentRemovalTemplate"
match=" nuggetVersion |nuggetId | ruleVersion | notes|ruleId | nuggetName | application | brlVersion | modelVersion | notes|declaration|preprocess " />
<xsl:template name="tagRemovalTemplate"
match=" ruleSection | blocks | block |actions | fieldRestriction | declaration | preprocess | tryCatchBlock |constraintList ">
<xsl:apply-templates />
<!-- set field and expression TBD -->
</xsl:template>
</xsl:stylesheet>
The Input file looks like below.
<?xml version="1.0" encoding="UTF-8"?>
<rule >
<name>IC-86</name>
<ruleId>1001</ruleId>
<ruleVersion>1.0</ruleVersion>
<nuggetId>1122</nuggetId>
<brlVersion>1.0</brlVersion>
<modelVersion>1.0</modelVersion>
<attributes>
<attribute>
<attributeName>agenda-group</attributeName>
<value>commonATSP</value>
</attribute>
</attributes>
<notes>Some text description about the rule, like what exactly it does...</notes>
<declaration />
<preprocess />
<ruleSection>
<blocks>
<block order="0">
<lhs>
<evaluate>
<leftOperand>
<boundVariable>
<variableName>$count</variableName>
<classType>Integer</classType>
<genericType>Number</genericType>
</boundVariable>
</leftOperand>
<comparisonOperator>gt</comparisonOperator>
<rightOperand>
<literal>10</literal>
</rightOperand>
</evaluate>
</lhs>
<rhs>
<modify>
<fieldValues>
<fieldValue>
<field>name</field>
<value>
<literal>$imageVersion</literal>
</value>
<nature>1</nature>
<type>String</type>
</fieldValue>
<fieldValue>
<field>value</field>
<value>
<callMethodOnBoundVariable>
<params>
<param>
<value>
<content>0</content>
<classType>int</classType>
<genericType>Numeric</genericType>
</value>
</param>
</params>
<boundVariableName>$attributes</boundVariableName>
<methodName>get</methodName>
<returnType>String</returnType>
</callMethodOnBoundVariable>
</value>
<nature>4</nature>
<type>String</type>
</fieldValue>
<fieldValue>
<field>type</field>
<value>
<literal>imageName</literal>
</value>
<nature>1</nature>
<type>String</type>
</fieldValue>
</fieldValues>
<variable>$attribute</variable>
</modify>
</rhs>
</block>
</blocks>
</ruleSection>
</rule>
I am facing an issue with my default namespace. I have a file with the root tag as below:
<rule xmlns="http://www.max.com/BRL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.max.com/BRL ../BRLV4.xsd ">
If I remove the namespaced <rule> as seen in the above input XML, then the translation works. Otherwise, it doesn't work. That is, if I try the translation without the default namespace then I am getting the required output as below. But I need the same output when I get the XML file with the default namespace on the root tag.
<?xml version="1.0" encoding="UTF-8"?>
<rule>
<name>IC-86</name>
<attributes>
<attribute>
<attributeName>agenda-group</attributeName>
<value>commonATSP</value>
</attribute>
</attributes>
<lhs>
<freeForm>
<text>eval($count > 10)</text>
</freeForm>
</lhs>
<rhs>
<freeForm>
<text>modify( $attribute ){ $imageVersion,$attributes.get(0),imageName };</text>
</freeForm>
</rhs>
</rule>
The default namespace in the XML document must be declared in the XSLT. For example, use the prefix 'brl'.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:brl="http://www.max.com/BRL">
Then use the brl prefix when referring to the tag names. For example,
<xsl:template match="brl:lhs" name="lhsTemplate">
...
<xsl:when test="brl:incident != ''">
<xsl:for-each select="brl:incident">
If the XML document may or may not have a namespace, see my article "Stay on the XPath: Tip 5: Handling XPath select expressions that fail to match documents with a default namespace" on IBM developerWorks.
Basically, you need your stylesheet to work whether all the elements are in no namespace, or in the BRL namespace. This is an odd requirement, and the ideal solution would be to tell your upstream data provider to be consistent about using the namespace.
But if you don't have that option, you have a few others.
1) Declare a prefix for the BRL namespace in your stylesheet, and use it to match elements in that namespace or in no namespace:
<xsl:stylesheet ... xmlns:BRL="http://www.max.com/BRL">
...
<xsl:template match="lhs | BRL:lhs">
...
2) Make all your matches and selects use local-name():
<xsl:template match="*[local-name()='lhs']">...
...
(Yuck!)
3) In XSLT 2.0, you can use the wildcard for namespaces:
<xsl:template match="*:lhs">
...
<xsl:when test="*:field/*:fieldName != ''">
But again, these three are all working around a problem in the source data. They are compensating for someone not using namespaces correctly, and thus enabling them to keep on doing the same. If the schema says the input document's elements should be in the "http://www.max.com/BRL" namespace, then you should assume that they are in that namespace (whether that's the default namespace is immaterial to you), so you should always be using a namespace prefix when matching or selecting those elements with XPath.
I'm transforming my XSLT-stylesheets into documentation, and I want a rich experience within the comment nodes for each code-chunk, therefore I want to convert the following comment and output as xhtml:
String:
# This is a title with __bold__ text and *italic* #
This is just a normal line
- list point with some __bold__
- list point with a "link"[http://www.stackoverflow.com]
Wanted output:
<h1> This is a title with <strong>bold</strong> and <span>italic</span> </h1>
<p>This is a normal line</p>
<ul>
<li>list point with some <strong>bold</strong></li>
<li>list point with a link</li>
</ul>
I tried with a recursive function that uses xsl:analyze-string recursively from a ruleset, but can't find a solution that works really well.
Anyone have done this lately, or is there some frameworks out there that has functions to do this ?
thanx in advance! :)
Edit: Added one dirty example:
<!-- Output comments -->
<xsl:template match="comment()" mode="COMMENT">
<xsl:copy-of select="ips:groupReplace(normalize-space(.),
'
(.*)(\n|\r)(.*),
(.*)\*(.*)\*(.*),
(.*)\*\*(.*)\*\*(.*),
(.*)__(.*)__(.*),
(.*)#(.*)#(.*),
(.*)-(.*)
',
'
br,
span.italic,
span.bold,
strong,
h1,
li
')" />
</xsl:template>
<!-- Initializing the iterateRegex function -->
<xsl:function name="ips:groupReplace">
<xsl:param name="string" as="xs:string" />
<xsl:param name="search" />
<xsl:param name="replace" />
<xsl:variable name="regex" select="tokenize($search, ',')" />
<xsl:variable name="replacements" select="tokenize($replace, ',')" />
<xsl:copy-of select="ips:iterateRegex(count($replacements), $string, $regex, $replacements)" />
</xsl:function>
<!-- Iterate each regex -->
<xsl:function name="ips:iterateRegex">
<xsl:param name="counter" />
<xsl:param name="string" />
<xsl:param name="list_regex" />
<xsl:param name="list_replace" />
<xsl:variable name="newStr">
<xsl:analyze-string select="$string" regex="{normalize-space($list_regex[$counter])}" flags="xm">
<xsl:matching-substring>
<xsl:variable name="cc" select="contains($list_replace[$counter], '.')" />
<xsl:variable name="tag" select="normalize-space(if ($cc) then (substring-before($list_replace[$counter], '.')) else ($list_replace[$counter]))" />
<xsl:copy-of select="regex-group(1)" />
<xsl:choose>
<xsl:when test="normalize-space(regex-group(2)) = ''">
<xsl:element name="{$tag}" />
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$tag}" >
<xsl:if test="$cc">
<xsl:attribute name="class" select="substring-after($list_replace[$counter],'.')" />
</xsl:if>
<xsl:copy-of select="regex-group(2)" />
</xsl:element>
</xsl:otherwise>
</xsl:choose>
<xsl:copy-of select="regex-group(3)" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:copy-of select="." />
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:variable>
<xsl:variable name="count" select="number($counter) - 1" />
<xsl:choose>
<xsl:when test="$count > 0">
<xsl:copy-of select="ips:iterateRegex($count, $newStr, $list_regex, $list_replace)" />
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$newStr" />
</xsl:otherwise>
</xsl:choose>
</xsl:function>
I think you would need a parser. So this stylesheet implements a verbose one:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text" name="block">
<xsl:param name="pString" select="."/>
<xsl:if test="$pString != ''">
<xsl:choose>
<xsl:when test="starts-with($pString,'#')">
<xsl:call-template name="header">
<xsl:with-param name="pString"
select="substring($pString,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($pString,'
')">
<xsl:call-template name="list">
<xsl:with-param name="pString"
select="substring($pString,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="paragraph">
<xsl:with-param name="pString"
select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template name="header">
<xsl:param name="pString"/>
<xsl:variable name="vInside"
select="substring-before($pString,'#
')"/>
<xsl:choose>
<xsl:when test="$vInside != ''">
<h1>
<xsl:call-template name="inline">
<xsl:with-param name="pString" select="$vInside"/>
</xsl:call-template>
</h1>
<xsl:call-template name="block">
<xsl:with-param name="pString"
select="substring-after($pString,'#
')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="paragraph">
<xsl:with-param name="pString"
select="concat('#',$pString)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="list">
<xsl:param name="pString"/>
<xsl:variable name="vCheckList" select="starts-with($pString,'- ')"/>
<xsl:choose>
<xsl:when test="$vCheckList">
<ul>
<xsl:call-template name="listItem">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</ul>
<xsl:call-template name="block">
<xsl:with-param name="pString">
<xsl:call-template name="afterlist">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="block">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="paragraph">
<xsl:param name="pString"/>
<xsl:choose>
<xsl:when test="contains($pString,'
')">
<p>
<xsl:value-of select="substring-before($pString,'
')"/>
</p>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:value-of select="$pString"/>
</p>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="block">
<xsl:with-param name="pString"
select="substring-after($pString,'
')"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="afterlist">
<xsl:param name="pString"/>
<xsl:choose>
<xsl:when test="starts-with($pString,'- ')">
<xsl:call-template name="afterlist">
<xsl:with-param name="pString"
select="substring-after($pString,'
')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pString"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="listItem">
<xsl:param name="pString"/>
<xsl:if test="starts-with($pString,'- ')">
<li>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="substring-before(substring($pString,3),'
')"/>
</xsl:call-template>
</li>
<xsl:call-template name="listItem">
<xsl:with-param name="pString"
select="substring-after($pString,'
')"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="inline">
<xsl:param name="pString" select="."/>
<xsl:if test="$pString != ''">
<xsl:choose>
<xsl:when test="starts-with($pString,'__')">
<xsl:call-template name="strong">
<xsl:with-param name="pString"
select="substring($pString,3)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($pString,'*')">
<xsl:call-template name="span">
<xsl:with-param name="pString"
select="substring($pString,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($pString,'"')">
<xsl:call-template name="link">
<xsl:with-param name="pString"
select="substring($pString,2)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($pString,1,1)"/>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="substring($pString,2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
<xsl:template name="strong">
<xsl:param name="pString"/>
<xsl:variable name="vInside" select="substring-before($pString,'__')"/>
<xsl:choose>
<xsl:when test="$vInside != ''">
<strong>
<xsl:value-of select="$vInside"/>
</strong>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="substring-after($pString,'__')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'__'"/>
<xsl:call-template name="inline">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="span">
<xsl:param name="pString"/>
<xsl:variable name="vInside" select="substring-before($pString,'*')"/>
<xsl:choose>
<xsl:when test="$vInside != ''">
<span>
<xsl:value-of select="$vInside"/>
</span>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="substring-after($pString,'*')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'*'"/>
<xsl:call-template name="inline">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="link">
<xsl:param name="pString"/>
<xsl:variable name="vInside"
select="substring-before($pString,'"')"/>
<xsl:choose>
<xsl:when test="$vInside != ''">
<xsl:call-template name="href">
<xsl:with-param name="pString"
select="substring-after($pString,'"')"/>
<xsl:with-param name="pInside" select="$vInside"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="'"'"/>
<xsl:call-template name="inline">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="href">
<xsl:param name="pString"/>
<xsl:param name="pInside"/>
<xsl:variable name="vHref"
select="substring-before(substring($pString,2),']')"/>
<xsl:choose>
<xsl:when test="starts-with($pString,'[') and $vHref != ''">
<a href="{$vHref}">
<xsl:value-of select="$pInside"/>
</a>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="substring-after($pString,']')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('"',$pInside,'"')"/>
<xsl:call-template name="inline">
<xsl:with-param name="pString" select="$pString"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
With this input:
<text>
# This is a title with __bold__ text and *italic* #
This is just a normal line
- list point with some __bold__
- list point with a "link"[http://www.stackoverflow.com]
</text>
Output:
<h1> This is a title with
<strong>bold</strong> text and
<span>italic</span>
</h1>
<p>This is just a normal line</p>
<ul>
<li>list point with some
<strong>bold</strong>
</li>
<li>list point with a
link
</li>
</ul>
Note: Look how many templates are similar (they follow a pattern), so these could be parametrized. I didn't do that in this case because there seems to be more questions which need some sort of parser, so by the end of the week I will repost an answer implementing functional parser and parser combinators pattern that make very easy to write parsers (just writing its grammar rules).
Edit: XSLT 2.0 solution. This stylesheet:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text">
<xsl:param name="pString" select="."/>
<xsl:analyze-string select="$pString"
regex="(#(.*)#
)|((- (.*)
)+)">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
<h1>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="regex-group(2)"/>
</xsl:call-template>
</h1>
</xsl:when>
<xsl:when test="regex-group(3)">
<ul>
<xsl:call-template name="list">
<xsl:with-param name="pString"
select="regex-group(3)"/>
</xsl:call-template>
</ul>
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:if test=".!='
'">
<p>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="normalize-space(.)"/>
</xsl:call-template>
</p>
</xsl:if>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template name="list">
<xsl:param name="pString"/>
<xsl:analyze-string select="$pString" regex="- (.*)
">
<xsl:matching-substring>
<li>
<xsl:call-template name="inline">
<xsl:with-param name="pString"
select="regex-group(1)"/>
</xsl:call-template>
</li>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:template>
<xsl:template name="inline">
<xsl:param name="pString" select="."/>
<xsl:analyze-string select="$pString"
regex="(__(.*)__)|(\*(.*)\*)|("(.*)"\[(.*)\])">
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
<strong>
<xsl:value-of select="regex-group(2)"/>
</strong>
</xsl:when>
<xsl:when test="regex-group(3)">
<span>
<xsl:value-of select="regex-group(4)"/>
</span>
</xsl:when>
<xsl:when test="regex-group(5)">
<a href="{regex-group(7)}">
<xsl:value-of select="regex-group(6)"/>
</a>
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
Output:
<h1> This is a title with
<strong>bold</strong> text and
<span>italic</span>
</h1>
<p>This is just a normal line</p>
<ul>
<li>list point with some
<strong>bold</strong>
</li>
<li>list point with a
link
</li>
</ul>
This transformation (111 lines):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my"
exclude-result-prefixes="xml xsl xs my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="vLines" select="tokenize(., '\n')"/>
<xsl:sequence select="my:parse-lines($vLines)"/>
</xsl:template>
<xsl:function name="my:parse-lines" as="element()*">
<xsl:param name="pLines" as="xs:string*"/>
<xsl:sequence select=
"my:parse-line($pLines, 1, count($pLines))"/>
</xsl:function>
<xsl:function name="my:parse-line" as="element()*">
<xsl:param name="pLines" as="xs:string*"/>
<xsl:param name="pLineNum" as="xs:integer"/>
<xsl:param name="pTotalLines" as="xs:integer"/>
<xsl:if test="not($pLineNum gt $pTotalLines)">
<xsl:variable name="vLine" select="$pLines[$pLineNum]"/>
<xsl:variable name="vLineLength"
select="string-length($vLine)"/>
<xsl:choose>
<xsl:when test=
"starts-with($vLine, '#')
and
ends-with($vLine, '#')
">
<xsl:variable name="vInnerString"
select="substring($vLine, 2, $vLineLength -2)"/>
<h1>
<xsl:sequence select="my:parse-string($vInnerString)"/>
</h1>
<xsl:sequence select=
"my:parse-line($pLines, $pLineNum+1, $pTotalLines)"/>
</xsl:when>
<xsl:when test=
"starts-with($vLine, '- ')
and
not(starts-with($pLines[$pLineNum -1], '- '))
">
<ul>
<li>
<xsl:sequence select="my:parse-string(substring($vLine, 2))"/>
</li>
<xsl:sequence select=
"my:parse-line($pLines, $pLineNum+1, $pTotalLines)"/>
</ul>
</xsl:when>
<xsl:when test="starts-with($vLine, '- ')">
<li>
<xsl:sequence select="my:parse-string(substring($vLine, 2))"/>
</li>
<xsl:sequence select=
"my:parse-line($pLines, $pLineNum+1, $pTotalLines)"/>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:sequence select="my:parse-string($vLine)"/>
</p>
<xsl:sequence select=
"my:parse-line($pLines, $pLineNum+1, $pTotalLines)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:function>
<xsl:function name="my:parse-string" as="node()*">
<xsl:param name="pS" as="xs:string"/>
<xsl:analyze-string select="$pS" flags="x" regex=
'(__(.*?)__)
|
(\*(.*?)\*)
|
("(.*?)"\[(.*?)\])
'>
<xsl:matching-substring>
<xsl:choose>
<xsl:when test="regex-group(1)">
<strong>
<xsl:sequence select="my:parse-string(regex-group(2))"/>
</strong>
</xsl:when>
<xsl:when test="regex-group(3)">
<span>
<xsl:sequence select="my:parse-string(regex-group(4))"/>
</span>
</xsl:when>
<xsl:when test="regex-group(5)">
<a href="{regex-group(7)}">
<xsl:sequence select="regex-group(6)"/>
</a>
</xsl:when>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:function>
</xsl:stylesheet>
when applied on this XML document (the provided text complicated with nested constructs and wrapped in an element):
<t># This is a title with __bold__ text and *italic* #
This is just a normal line
- list point with some __bold__
- list point with a __*"link"[http://www.stackoverflow.com]*__</t>
produces the wanted, correct output:
<h1> This is a title with <strong>bold</strong> text and <span>italic</span>
</h1>
<p>This is just a normal line</p>
<p/>
<ul>
<li> list point with some <strong>bold</strong>
</li>
<li> list point with a <strong>
<span>
link
</span>
</strong>
</li>
</ul>
Do note: The RegEx mechanism of XPath 2.0 and XSLT 2.0 is adequate for solving this problem.