I've the below code in XML.
<?xml version="1.0" encoding="UTF-8"?>
<toa>
<title>TABLE OF HONG KONG LEGISLATION</title>
<subtitle>All references are to paragraph number</subtitle>
<toa-section>
<toa-div level="div1">
<title/>
<toa-entry>
<primary-entry>
<entry-name>Banking Ordinance (Cap.155)</entry-name>
<pgs>7.040</pgs>
</primary-entry>
</toa-entry>
</toa-div>
</toa-section>
</toa>
and the XSLT is as below.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:text disable-output-escaping="yes"><!DOCTYPE html>
</xsl:text>
<html>
<head>
<xsl:text disable-output-escaping="yes"><![CDATA[</meta>]]></xsl:text>
<title>TABLE OF LEGISLATION</title>
<link rel="stylesheet" href="C:\Users\u0138039\Desktop\In Progress\Company Law-Insolvency 2014 Edition_xml\XSLT\main.css" type="text/css" /><xsl:text disable-output-escaping="yes"><![CDATA[</link>]]></xsl:text>
</head>
<body>
<section class="tr_toa">
<xsl:call-template name="toa"></xsl:call-template>
</section>
</body>
</html>
</xsl:template>
<xsl:template name="toa">
<div class="toa">
<a name="CLI_TOL_01"> </a>
<xsl:apply-templates />
</div>
</xsl:template>
<xsl:template match="toa/title">
<div class="toa-title">
<xsl:value-of select="current()/content-style/text()"/>
</div>
</xsl:template>
<xsl:template match="toa-section">
<div class="toa-section">
<xsl:for-each select="current()/toa-div">
<xsl:call-template name="toa-div" />
</xsl:for-each>
</div>
</xsl:template>
<xsl:template match="toa-div" name="toa-div">
<xsl:variable name="divClass" select="concat('toa-div level-', current()/#level)"></xsl:variable>
<div class="{$divClass}">
<div class="toa-div-title">
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',title/content-style/#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:value-of select="current()/title/content-style/text()"/>
</span>
</div>
<xsl:apply-templates select="toa-entry" />
</div>
</xsl:template>
<xsl:template match="toa-entry">
<xsl:choose>
<xsl:when test="not(preceding-sibling::toa-entry[1]/primary-entry/secondary-entry/node()) and position() != 1">
</xsl:when>
<xsl:otherwise>
<table class="toa-entry">
<tbody>
<xsl:apply-templates select="primary-entry" />
<xsl:if test="not(current()/primary-entry/secondary-entry/node())">
<xsl:apply-templates select="following-sibling::toa-entry[1]" mode="next"/>
</xsl:if>
</tbody>
</table>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="toa-entry" mode="next">
<xsl:apply-templates select="primary-entry"/>
<xsl:if test="not(current()/primary-entry/secondary-entry/node())">
<xsl:apply-templates select="following-sibling::toa-entry[1]" mode="next"/>
</xsl:if>
</xsl:template>
<xsl:template match="primary-entry">
<tr class="primary-entry">
<td class="entry-name">
<xsl:value-of select="current()/entry-name/text()"/>
</td>
<xsl:if test="current()/pgs/node()">
<td class="pgs" >
<xsl:variable name="pgcount" select="count(current()/pgs)"/>
<xsl:for-each select="current()/pgs">
<xsl:apply-templates select="./pgs"></xsl:apply-templates>
</xsl:for-each>
</td>
</xsl:if>
</tr>
<xsl:if test="current()/secondary-entry/node()">
<xsl:for-each select="current()/secondary-entry">
<tr class="secondary-entry">
<td class="entry-name">
<xsl:value-of select="current()/entry-name/text()"/>
</td>
<xsl:if test="current()/pgs/node()">
<td class="pgs" >
<xsl:variable name="pgcount" select="count(current()/pgs)"/>
<xsl:for-each select="current()/pgs">
<xsl:apply-templates></xsl:apply-templates>
</xsl:for-each>
</td>
</xsl:if>
</tr>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template match="pgs">
<td class="pgs">
<xsl:analyze-string select="." regex="[^,\s]+">
<xsl:matching-substring>
<xsl:variable name="range" select="tokenize(.,'—')"/>
<xsl:variable name="pg" select="tokenize(.,'/')"/>
<xsl:choose>
<xsl:when test="contains($pg[3],'—')">
<xsl:variable name="range-pg" as="item()*">
<xsl:for-each select="$range">
<xsl:sequence select="tokenize(.,'/')"/>
</xsl:for-each>
</xsl:variable>
<xsl:for-each select="xs:integer($range-pg[3]) to xs:integer($range-pg[6])">
<a href="er:#HKWBV1_ORD_{
if (string(number($range-pg[1]))!='NaN') then
format-number(number($range-pg[1]),'00')
else
$range-pg[1]}/P{string-join($range-pg[position()=(1,2)],'/')}/{.}">
<xsl:value-of select="concat(string-join($range-pg[position()=(1,2)],'/'),'/',.)"/>
</a>
<xsl:text>, </xsl:text>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<a href="er:#HKWBV1_ORD_{
if (string(number($pg[1]))!='NaN') then
format-number(number($pg[1]),'00')
else
$pg[1]}/P{$pg[1]
}/{string-join($pg[position()>1],'/')}">
<xsl:value-of select="."/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</td>
</xsl:template>
</xsl:stylesheet>
though i have written a template match for pgs, while debugging, the flow is not entering the template. Please let me know where am i going wrong.
Thanks
change
<xsl:template match="primary-entry">
<tr class="primary-entry">
<td class="entry-name">
<xsl:value-of select="current()/entry-name/text()"/>
</td>
<xsl:if test="current()/pgs/node()">
<td class="pgs" >
<xsl:variable name="pgcount" select="count(current()/pgs)"/>
<xsl:for-each select="current()/pgs">
<xsl:apply-templates select="./pgs"></xsl:apply-templates>
</xsl:for-each>
</td>
</xsl:if>
to
<xsl:template match="primary-entry">
<tr class="primary-entry">
<td class="entry-name">
<xsl:value-of select="current()/entry-name/text()"/>
</td>
<xsl:if test="current()/pgs/node()">
<xsl:apply-templates select="pgs"/>
</xsl:if>
and do the same for the secondary template.
Related
The goal is simple. I'm trying to build a table with attributes in columns.
My problem : Some siblings don't have the same attributes as the first one.
When I build the table head I retrieve the attributes name of the first node and then hope that attributes of the following siblings will be the same in the same order. That is not the case.
I get only columns id, key, value, myattr1 and the myattr2 attribute is placed in the myattr1 column.
For building the table, I want to get columns : id, key, value, myattr1, myattr2
How can I retrieve the whole list of existing attributes for the node I am working on and loop over it?
I am still working the same js and form (see link at the bottom). It now requires bootstrap (css and js).
I slightly changed the xml. Here it is :
<?xml version="1.0" encoding="UTF-8"?>
<Domain>
<Properties id="myid">
<Property id="DOM00000" key="mykey1" value="value1" myattr2="Mail"/>
<Property id="DOM00001" key="mykey2" value="value2" myattr1="EveryDay"/>
</Properties>
<Tokens>
<Token name="token1" comment="" ><![CDATA[mydata1---blah-blah-blah]]></Token>
<Token name="token2" comment="" ><![CDATA[mydata2---blah-blah-blah]]></Token>
</Tokens>
<Resources>
<Resource name="res1" type="W" current="0">
<Value><![CDATA[10]]></Value>
</Resource>
<Resource name="res2" type="W" current="0">
<Value><![CDATA[10]]></Value>
</Resource>
</Resources>
</Domain>
The current state of the xsl :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<xsl:element name="div">
<xsl:attribute name="class">container</xsl:attribute>
<ul class="nav nav-tabs">
<xsl:for-each select="./*">
<xsl:call-template name="tabs" />
</xsl:for-each>
</ul>
</xsl:element>
<xsl:element name="div">
<xsl:attribute name="class">tab-content</xsl:attribute>
<xsl:for-each select="./*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="tabs">
<xsl:variable name="active">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">nav-link</xsl:attribute>
<xsl:attribute name="data-toggle">tab</xsl:attribute>
<xsl:value-of select="name(.)" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="activetab">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active in</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="div">
<xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
<h3><xsl:value-of select="name(.)" /></h3>
<table class="table table-striped table-hover">
<thead>
<tr><xsl:for-each select="./*[1]/#*"><th><xsl:value-of select="name(.)" /></th></xsl:for-each></tr>
</thead>
<tbody>
<xsl:for-each select="./*"><tr>
<xsl:for-each select="./#*"><td><xsl:value-of select="." /></td></xsl:for-each></tr>
</tr></xsl:for-each>
</tbody>
</table>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XSLT - How to manage CDATA as common content?
Edit :
Thanks to Tim-C answer
Here is the full xsl working for my use case :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
<xsl:template match="/*">
<xsl:element name="div">
<xsl:attribute name="class">container</xsl:attribute>
<ul class="nav nav-tabs">
<xsl:for-each select="./*">
<xsl:call-template name="tabs" />
</xsl:for-each>
</ul>
</xsl:element>
<xsl:element name="div">
<xsl:attribute name="class">tab-content</xsl:attribute>
<xsl:for-each select="./*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="tabs">
<xsl:variable name="active">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">nav-link</xsl:attribute>
<xsl:attribute name="data-toggle">tab</xsl:attribute>
<xsl:value-of select="name(.)" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="activetab">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active in</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
<xsl:element name="div">
<xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
<h3><xsl:value-of select="name(.)" /></h3>
<table class="table table-striped table-hover">
<thead>
<tr>
<xsl:for-each select="$attrs">
<th>
<xsl:value-of select="name()" />
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="*">
<tr>
<xsl:variable name="current" select="." />
<xsl:for-each select="$attrs">
<td>
<xsl:value-of select="$current/#*[name() = name(current())]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:element>
</xsl:template>
<xsl:template name="toto"></xsl:template>
</xsl:stylesheet>
What you make use of here is a technique called Muenchian Grouping to get a list of distinct attributes, based on their name.
However, although the question just mentions about id, key, value, myattr1, myattr2, which are the Property attributes, it looks like you want to repeat it for the Token and Resource nodes too (i.e. you are trying to be generic). In this case, you define a key like so, which takes into account the main element name
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
Then, for a given element (such as Properties) you can get distinct attributes like so:
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
This can then be used to get the headers, and access the relevant attributes for each row.
Try this (abridged) XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
<xsl:template match="/*">
<xsl:for-each select="*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
<table class="table table-striped table-hover">
<thead>
<tr>
<xsl:for-each select="$attrs">
<th>
<xsl:value-of select="name()" />
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="*">
<tr>
<xsl:variable name="current" select="." />
<xsl:for-each select="$attrs">
<td>
<xsl:value-of select="$current/#*[name() = name(current())]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
See it in action at http://xsltfiddle.liberty-development.net/jyRYYi7
I've the below line in XML.
<tb class="3">
<tr>
<td>
<b>English words </b>
</td>
<td>
<b>Arabic </b>
</td>
<td al="r">
<b>Arabic</b>
</td>
</tr>
<tr>
<td>bear </td>
<td>ḍam</td>
<td al="r">new</td>
</tr>
</tb>
Here is my xslt.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#class)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<!-- I want the condition here-->
</colgroup>
</xsl:template>
This gives me output of 33.3. And I want to create 3 cols(the class attribute value). And for each col the name should be increment value. as below.
<col name="1" width="33.3"/>
<col name="2" width="33.3"/>
<col name="3" width="33.3"/>
please let me know, how can i get the above result.
Thanks
Here is my answer.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<!--<xsl:apply-templates/>-->
</table>
</xsl:template>
<xsl:template name="colgroup">
<xsl:param name="count" select="./#cls"/>
<xsl:param name="final" select="1"/>
<xsl:variable name="colcnt" select="format-number(100 div number(./#cls),'##.#')"/>
<col class="colnum-{$final} colname-col{$final} colwidth-{$colcnt}"></col>
<xsl:if test="$final < $count">
<xsl:call-template name="colgroup">
<xsl:with-param name="final" select="$final +1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#cls)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<xsl:call-template name="colgroup"/>
</colgroup>
<xsl:for-each select="tr">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="tr">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="td">
<td>
<xsl:attribute name="align">
<xsl:choose>
<xsl:when test="./#al='r'">
<xsl:text>right</xsl:text>
</xsl:when>
<xsl:when test="./#al='c'">
<xsl:text>center</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>left</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates/>
</td>
</xsl:template>
If you are using XSLT 2.0, then one way to generate a specific number of elements, in your case col elements, is to use a variation of the xsl:for-each to do a specific number of iterations.
So, instead of doing <xsl:call-template name="colgroup"/> to call a recursive template, you could do this:
<colgroup>
<xsl:for-each select="1 to xs:integer($numbr)">
<col name="{.}" width="{$colcnt}"/>
</xsl:for-each>
</colgroup>
Note that you will need to define the xs namespace prefix in your stylesheet as follows
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
i've the below xslt
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ntw="Number2Word.uri" exclude-result-prefixes="ntw">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<xsl:text disable-output-escaping="yes"><![CDATA[</meta>]]></xsl:text>
<link rel="stylesheet" href="C:\Documents and Settings\u0138039\Desktop\Per\NEW.css" type="text/css"></link>
</head>
<body>
<section class="tr_chapter">
<div class="chapter">
<xsl:apply-templates/>
</div>
</section>
</body>
</html>
</xsl:template>
<xsl:template match="case">
<xsl:apply-templates select="case.head"/>
</xsl:template>
<xsl:template match="case.head">
<div class="section-sect0">
<div class="para">
<xsl:value-of select="./party.line/party[#role='Plaintiff']"/>
</div>
</div>
<div class="section-sect0">
<div class="para">
<xsl:text disable-output-escaping="yes">V</xsl:text>
</div>
</div>
<div class="section-sect0">
<div class="para">
<xsl:value-of select="./party.line/party[#role='Defendant']"/>
</div>
</div>
<xsl:apply-templates select="case.ref.no.group | judge.line"/>
</xsl:template>
<xsl:template match="para">
<div class="para">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="case.ref.no.group">
<div class="section-sect3">
<span class="font-style-bold">Court of Appeal</span>
<xsl:text> - </xsl:text>
<xsl:value-of select="case.ref.no[1]/prefix" />
<xsl:text> Nos. </xsl:text>
<xsl:for-each select="case.ref.no">
<xsl:value-of select="number" />
<xsl:text>-</xsl:text>
<xsl:value-of select="year" />
<xsl:if test="not(position() = 2)">
</xsl:if>
</xsl:for-each>
</div>
</xsl:template>
<xsl:template match="judge.line">
<div class="section-sect3">
<xsl:for-each select="judge">
<xsl:value-of select="name"/>
<xsl:if test="not(position() = last())">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:text> JC</xsl:text>
</div>
<xsl:apply-templates select="following-sibling::date.group"></xsl:apply-templates>
</xsl:template>
<xsl:template match="date.group">
<div class="section-sect4">
<div class="para">
<xsl:value-of select="./date.line/date"/>
</div>
</div>
<xsl:apply-templates select="//catchwords.group"/>
</xsl:template>
<xsl:template match="catchwords.group">
<div class="y">
<xsl:for-each select="catchwords/catchword">
<xsl:choose>
<xsl:when test="#level=1"><br/>
<span class="font-style-bolditalic">
<xsl:value-of select="."/>
</span>
<xsl:text disable-output-escaping="yes">-</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select=".">
<xsl:value-of select="."></xsl:value-of>
<xsl:if test="not(position() = last()-1)">
<xsl:text disable-output-escaping="yes"> – </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</div>
<xsl:apply-templates select="//headnotes"/>
</xsl:template>
<xsl:template match="headnotes/para">
<xsl:choose>
<xsl:when test="position()=1">
<div class="x">
<xsl:apply-templates></xsl:apply-templates>
</div>
</xsl:when>
<xsl:otherwise>
<div class="m">
<xsl:apply-templates/>
</div>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates select="para.group"/>
</xsl:template>
<xsl:template match="para.group">
<div class="section-sect1">
<xsl:value-of select="./heading"/>
</div>
<xsl:for-each select="./para">
<xsl:apply-templates select="node()[not(self::label)]"/>
</xsl:for-each>
<xsl:apply-templates select="//counsel.group"/>
</xsl:template>
<xsl:template name="orderedlist" match="list">
<ol class="eng-orderedlist orderedlist">
<xsl:apply-templates select="list.item/label"/>
</ol>
</xsl:template>
<xsl:template name="orderitempara" match="list.item/label">
<li class="item">
<div class="para">
<span class="item-num">
<xsl:choose>
<xsl:when test="following-sibling::case.considered">
<xsl:apply-templates/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</span>
<xsl:apply-templates select="parent::list.item"/>
</div>
</li>
</xsl:template>
<xsl:template match="list.item">
<xsl:variable name="a">
<xsl:value-of select="./label"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="./label">
<xsl:apply-templates select="child::node()[not(self::label|case.ref)]"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template match="counsel.group" name="j">
<div class="ital">
<xsl:for-each select="./counsel.line">
<div class="para">
<xsl:value-of select="."/>
</div>
</xsl:for-each>
<xsl:text disable-output-escaping="yes">Judgment received: December 4, 2008</xsl:text>
</div>
<xsl:apply-templates select="//ref.group"/>
</xsl:template>
<xsl:template match="ref.group/leg.mentioned">
<div class="section-sect1">
<xsl:text>Legislation mentioned in the judgment</xsl:text>
</div>
<xsl:for-each select="./leg.ref">
<div class="para">
<xsl:value-of select="./citetitle"/>
<xsl:text>, </xsl:text>
<xsl:for-each select="./leg.ptr.group/leg.ptr">
<xsl:value-of select="."/>
<xsl:if test="not(position() = last())">
<xsl:text disable-output-escaping="yes">, </xsl:text>
</xsl:if>
</xsl:for-each>
</div>
</xsl:for-each>
<xsl:text>Cases cited in the judgment</xsl:text>
<xsl:for-each select="//citetitle">
<xsl:if test="parent::case.ref/#annotation">
<div class="ital">
<div class="para">
<xsl:value-of select="."/>
<xsl:value-of select="//citecitation"/>
<xsl:value-of select="parent::case.ref/#court"/>
<xsl:text> (</xsl:text>
<xsl:value-of select="parent::case.ref/#annotation"/>
<xsl:text>)</xsl:text>
</div>
</div>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="//judgment"/>
</xsl:template>
<xsl:template match="judgment">
<div class="section-sect1">
<xsl:value-of select="./judge.block/heading/judgename"/>
</div>
<xsl:for-each select="./judge.block/para">
<div class="para">
<span class="new">
<xsl:value-of select="./label"></xsl:value-of>
</span>
<xsl:value-of select="./text()"/>
</div>
<xsl:apply-templates select="./list"/>
</xsl:for-each>
<xsl:for-each select="./judge.block/para.group">
<xsl:if test="./heading">
<div class="section-sect1">
<xsl:value-of select="./heading/text()"/>
</div>
</xsl:if>
<xsl:for-each select="para">
<div class="para">
<span class="new">
<xsl:value-of select="./label"></xsl:value-of>
</span>
<xsl:apply-templates select="child::node()[not(self::label)]"/>
</div>
<xsl:apply-templates select="./list"/>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="emphasis">
<xsl:choose>
<xsl:when test="citetitle">
<span class="font-style-italic">
<xsl:apply-templates select="./list.item"/>
</span>
</xsl:when>
<xsl:when test="./#type">
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#type)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:apply-templates/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
when i apply this on my below part of my xml it is giving me a stackoverflow error.
<?xml version="1.0" encoding="UTF-8"?>
<case>
<counsel.group>
<counsel.line>Azar Irwan b Moh Arifin (AG’s Chambers) for Public Prosecutor</counsel.line>
<counsel.line>SK Pari (Pari & Co) for first accused</counsel.line></counsel.group>
<ref.group>
<leg.mentioned>
<leg.ref country="India">
<citetitle type="leg" legtype="ord">Indian Penal Code</citetitle>
<leg.ptr.group>
<leg.ptr provision="s" print="yes">302</leg.ptr>
</leg.ptr.group>
</leg.ref>
<leg.ref country="Malaysia">
<citetitle type="leg" legtype="ord">Criminal Procedure Code</citetitle>
<leg.ptr.group>
<leg.ptr provision="ss" print="yes">112</leg.ptr>
<leg.ptr provision="s" print="no">112</leg.ptr>
</leg.ptr.group>
</leg.ref>
<leg.ref country="Malaysia">
<citetitle type="leg" legtype="ord">Penal Code</citetitle>
<leg.ptr.group>
<leg.ptr provision="ss" print="yes">109</leg.ptr>
<leg.ptr provision="s" print="no">299</leg.ptr>
</leg.ptr.group>
</leg.ref>
</leg.mentioned></ref.group>
</case>
please let me know how do i resolve this error and what are the steps to be followed so that in future i don't encounter this error.
Thanks
Your XSLT contains an infinite loop. Your para.group template contains this:
<xsl:apply-templates select="//counsel.group"/>
And then the template for counsel.group has this:
<xsl:apply-templates select="//ref.group"/>
The template for ref.group has this:
<xsl:apply-templates select="//judgment"/>
The template for judgment has this:
<xsl:for-each select="para">
...
<xsl:apply-templates select="child::node()[not(self::label)]"/>
...
</xsl:for-each>
Which cascades down to apply templates on a para.group and then you're back at the beginning. This process goes around in circles until the stack overflows. I think you need to rethink your XSLT to figure out how to prevent infinite recursion.
I have an XML file with this format:
<?xml version="1.0" encoding="utf-8" ?>
<OpacResult>
<valueObjects class="list">
<Catalog>
<notes>
Daily newsletter available via e-mail.
IP authenticated. Login not needed within firm.
</notes>
<title>Health law360. </title>
<url>http://health.law360.com/</url>
<catalogTitles class="list">
<CatalogTitle>
<uuid>e5e2bc53ac1001f808cddc29f93ecad8</uuid>
<timeChanged class="sql-timestamp">2010-12-14 09:17:10.707</timeChanged>
<timeEntered class="sql-timestamp">2010-12-14 09:17:10.707</timeEntered>
<whoChanged>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoChanged>
<whoEntered>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoEntered>
<updateSearchIndex>true</updateSearchIndex>
<corpId>RopesGray</corpId>
<catalogUuid>a20b6b4bac1001f86d28280ed0ebeb9e</catalogUuid>
<type>O</type>
<title>Law 360. Health law.</title>
</CatalogTitle>
<CatalogTitle>
<uuid>e5e2bc53ac1001f808cddc299ddfe49d</uuid>
<timeChanged class="sql-timestamp">2010-12-14 09:17:10.707</timeChanged>
<timeEntered class="sql-timestamp">2010-12-14 09:17:10.707</timeEntered>
<whoChanged>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoChanged>
<whoEntered>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoEntered>
<updateSearchIndex>true</updateSearchIndex>
<corpId>RopesGray</corpId>
<catalogUuid>a20b6b4bac1001f86d28280ed0ebeb9e</catalogUuid>
<type>O</type>
<title>Health law 360</title>
</CatalogTitle>
<CatalogTitle>
<uuid>e5e2bc53ac1001f808cddc29ec1d959b</uuid>
<timeChanged class="sql-timestamp">2010-12-14 09:17:10.707</timeChanged>
<timeEntered class="sql-timestamp">2010-12-14 09:17:10.707</timeEntered>
<whoChanged>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoChanged>
<whoEntered>B23DE2FFE8DD49B0B0A03D1FEB3E7DA2</whoEntered>
<updateSearchIndex>true</updateSearchIndex>
<corpId>RopesGray</corpId>
<catalogUuid>a20b6b4bac1001f86d28280ed0ebeb9e</catalogUuid>
<type>O</type>
<title>Health law three hundred sixty</title>
</CatalogTitle>
</catalogTitles>
<catalogUrls class="list"/>
<gmd>
<uuid>f8f123acc0a816070192e296a6a71715</uuid>
<timeChanged class="sql-timestamp">2006-10-10 15:23:37.813</timeChanged>
<timeEntered class="sql-timestamp">2005-01-27 00:00:00.0</timeEntered>
<whoChanged>25db9fcd3fd247f4a20485b40cc134ad</whoChanged>
<whoEntered>user</whoEntered>
<updateSearchIndex>true</updateSearchIndex>
<corpId>RopesGray</corpId>
<isRuleDefault>false</isRuleDefault>
<ruleName>text</ruleName>
<term>electronic resource</term>
<preferCollection>false</preferCollection>
<isTechnicalManual>false</isTechnicalManual>
<sip2IsMagnetic>false</sip2IsMagnetic>
</gmd>
<issues class="list"/>
</Catalog>
</valueObjects>
</OpacResult>
As you can see, there are other elements under sibling nodes, but I don't care about these and only want to see the first one.
I'm using this code to call a template with the string of desired elements as the parameter
and a template to loop through the asterisk-delimited string parameter: (title*url*notes*)
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="columns" />
<xsl:template match="/OpacResult/valueObjects">
<html>
<body>
<table border="1">
<!-- Header row -->
<tr>
<xsl:call-template name="print-headers">
<xsl:with-param name="columns" select="$columns"/>
</xsl:call-template>
</tr>
<!-- Value rows -->
<xsl:for-each select="Catalog">
<tr>
<xsl:call-template name="print-values">
<xsl:with-param name="columns" select="$columns"/>
</xsl:call-template>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
<!-- Split up string of column names and create header field names based on element names-->
<xsl:template name="print-headers">
<xsl:param name="columns"/>
<xsl:variable name="newList" select="$columns"/>
<xsl:variable name="first" select="substring-before($newList, '*')" />
<xsl:variable name="remaining" select="substring-after($newList, '*')" />
<th>
<xsl:apply-templates select="Catalog/*[name()=$first]">
<xsl:with-param name="header">true</xsl:with-param>
</xsl:apply-templates>
</th>
<xsl:if test="$remaining">
<xsl:call-template name="print-headers">
<xsl:with-param name="columns" select="$remaining"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="print-values">
<xsl:param name="columns"/>
<xsl:variable name="newList" select="$columns"/>
<xsl:variable name="first" select="substring-before($newList, '*')" />
<xsl:variable name="remaining" select="substring-after($newList, '*')" />
<td>
<xsl:apply-templates select="Catalog/*[name()=$first]"/>
</td>
<xsl:if test="$remaining">
<xsl:call-template name="print-values">
<xsl:with-param name="columns" select="$remaining"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="title">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>Title</xsl:text>
</xsl:when>
<xsl:otherwise>
<a>
<xsl:attribute name="href">
<xsl:value-of select="//*[name()='url']"/>
</xsl:attribute>
<xsl:value-of select="//*[name()='title']"/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="url">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>URL</xsl:text>
</xsl:when>
<xsl:otherwise>
<a>
<xsl:attribute name="href">
<xsl:value-of select="//*[name()='url']"/>
</xsl:attribute>
<xsl:value-of select="//*[name()='url']"/>
</a>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="notes">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>Notes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//*[name()='notes']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="holdingNotes">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>Holding Notes</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//*[name()='holdingNotes']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="relatedUrl">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>Related URL</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//*[name()='relatedUrl']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="bibliographicType/hasDataFile">
<xsl:param name="header"/>
<xsl:choose>
<xsl:when test="$header='true'">
<xsl:text>File</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Catalog/*[name()='hasDataFile']"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The only way I can access this template is to use the //*[name()=$first] syntax to extract the value of the element based on the name from the $first parameter.
Any help is greatly appreciated. Thanks very much in advance. Not including the full XML as there are thousands of lines of unnecessary text.
This stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:h="header"
exclude-result-prefixes="h">
<h:h>
<title>Title</title>
<url>URL</url>
<notes>Notes</notes>
</h:h>
<xsl:param name="pColumns" select="'title url notes'"/>
<xsl:template match="/OpacResult/valueObjects">
<html>
<body>
<table border="1">
<tr>
<xsl:apply-templates
select="document('')/*/h:h"
mode="filter"/>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Catalog">
<tr>
<xsl:call-template name="filter"/>
</tr>
</xsl:template>
<xsl:template match="h:h/*">
<th>
<xsl:value-of select="."/>
</th>
</xsl:template>
<xsl:template match="Catalog/*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
<xsl:template match="node()" mode="filter" name="filter">
<xsl:apply-templates select="*[contains(
concat(' ',$pColumns,' '),
concat(' ',name(),' '))]">
<xsl:sort select="substring-before(
concat(' ',$pColumns,' '),
concat(' ',name(),' '))"/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
Output:
<html>
<body>
<table border="1">
<tr>
<th>Title</th>
<th>URL</th>
<th>Notes</th>
</tr>
<tr>
<td>Health law360. </td>
<td>http://health.law360.com/</td>
<td> Daily newsletter available via e-mail.
IP authenticated. Login not needed within firm. </td>
</tr>
</table>
</body>
</html>
Note: Inline data for headers, pseudo sequence parameter for filtering and sorting, modes not for processing the same element in different way but for processing different elements in the same way also.
I've found a solution, but I'm sure it's not the best way to do it. Within the templates for each of my expected fields, I have added:
<xsl:if test=position()=1">
.. process data here ..
</xsl:if>
Ideally, there would be a way to tell this to process only the first element it finds:
<th>
<xsl:apply-templates select="//*[name()=$first]">
<xsl:with-param name="header">true</xsl:with-param>
</xsl:apply-templates>
</th>
Edit: As I suspected, this will not work when there is more than one Catalog element to parse. So instead of grabbing the first element for each catalog parent element, it's grabbing the first element in the document every time
Need some help: I want to only pull back the results for a specific ItemId, so if i wanted the only data for ItemId how could I adapt the template below?
I've tried for about 2 hours without any luck...
Here is a sample of my XML:
This Xslt only brings the item with ItemId value equal to 2075.
Notice I added [ItemInfo/PeriodAttendanceInfo/ItemId=2075].
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:call-template name="dvt_2"/>
</xsl:template>
<xsl:template name="dvt_2">
<xsl:variable name="Rows" select="/ArrayOfPeriodAttendanceGroup/PeriodAttendanceGroup[ItemInfo/PeriodAttendanceInfo/ItemId=2075]"/>
<xsl:variable name="dvt_RowCount" select="count($Rows)"/>
<xsl:call-template name="dvt_2.rowContents">
<xsl:with-param name="Rows" select="$Rows"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="dvt_2.rowContents">
<xsl:param name="Rows"/>
<xsl:for-each select="$Rows">
<xsl:sort select="ItemInfo/PeriodAttendanceInfo" order="ascending"/>
<xsl:call-template name="dvt_2.rowContentsView"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="dvt_2.rowContentsView">
<xsl:variable name="subjectName" select="ItemInfo/PeriodAttendanceInfo/ItemText"/>
<tr class="{$subjectName}">
<xsl:element name="td">
<xsl:attribute name="class">
<xsl:value-of select="ItemInfo/PeriodAttendanceInfo/ItemText"/>
</xsl:attribute>
<xsl:variable name="subjectID" select="ItemInfo/PeriodAttendanceInfo/ItemId"/>
<a class="leftAlign" href="../Departments/{$subjectID}">
<xsl:value-of select="ItemInfo/PeriodAttendanceInfo/ItemText"/>
</a>
</xsl:element>
<td>
<p class="name">
<xsl:value-of select="Total"/>
</p>
</td>
<td>
<p class="name">
<xsl:value-of select="Present"/>
</p>
</td>
<td>
<p class="name">
<xsl:value-of select="Late"/>
</p>
</td>
<td>
<p class="name">
<xsl:value-of select="UnauthorisedAbsence"/>
</p>
</td>
</tr>
</xsl:template>
<xsl:template name="dvt_1.empty">
<xsl:variable name="dvt_ViewEmptyText">There is no timetable view for today</xsl:variable>
<table border="0" width="100%">
<tr>
<td class="ms-vb">
<xsl:value-of select="$dvt_ViewEmptyText"/>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>