template is not caught though declared correct - xslt

I've the below XML.
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<toc>
<toc-part>
<toc-div>
<toc-item>
<toc-title>2.1 Introduction</toc-title>
<toc-pg>179</toc-pg>
</toc-item>
</toc-div>
</toc-part>
</toc>
<section level="sect1">
<title><content-style font-style="bold">2.1 INTRODUCTION</content-style></title>
<section level="sect2">
<title><content-style font-style="bold">The bank</content-style></title>
<para num="2.1.1">
</para>
</section>
</section>
</chapter>
and below XSLT.
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:ntw="Number2Word.uri"
exclude-result-prefixes="ntw">
<xsl:output method="html"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="ThisDocument" select="document('')"/>
<xsl:template name="toc-item" match="chapter/toc/toc-part/toc-div/toc-item">
<xsl:variable name="tocpg">
<xsl:value-of select="concat('P',current()/toc-pg/text())"/>
</xsl:variable>
<xsl:variable name="tocpgtag" select="translate($tocpg,'.', '-')"/>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="strl">
<xsl:value-of select="string-length(substring-after(#num,'.'))"/>
</xsl:variable>
<xsl:variable name="Brac">
<xsl:choose>
<xsl:when test="contains(substring-after(#num,'.'),'.')">
<xsl:value-of select="3"/>
</xsl:when>
<xsl:when test="contains(#num,'(')">
<xsl:value-of select="2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="NewL">
<xsl:value-of select="string-length(substring-before(current()/toc-pg,'.'))"/>
</xsl:variable>
<xsl:variable name="newNum">
<xsl:choose>
<xsl:when test="$NewL=1">
<xsl:value-of select="concat('0',substring-before(current()/toc-pg/text(),'.'))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-before(current()/toc-pg/text(),'.')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="d">
<xsl:value-of select="concat('toc-item-',$ThisDocument//ntw:nums[#num=$Brac]/#word,'-level')"/>
</xsl:variable>
<xsl:variable name="new">
<xsl:value-of select="concat('er:#LRSC_CH_',$newNum,'/',$tocpgtag)"/>
</xsl:variable>
<table class="{$d}">
<tbody>
<tr>
<td class="toc-item-num">
<xsl:value-of select="current()/#num"/>
</td>
<td class="toc-title">
<xsl:value-of select="current()/toc-title"/>
</td>
<td class="toc-pg">
<xsl:variable name="refe">
<xsl:choose>
<xsl:when test="//section/title/content-style[upper-case(./text())=upper-case(current()/toc-title/text())]/section[1]/para[1]/#num[1]">
<xsl:value-of select="//section/title/content-style[upper-case(./text())=upper-case(current()/toc-title/text())]/section[1]/para[1]/#num[1]"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//section/title/content-style[upper-case(text())=upper-case(current()/toc-title/text())]/para[1]/#num[1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="full">
<xsl:value-of select="$refe"/>
</xsl:variable>
<xsl:variable name="pre">
<xsl:value-of select="substring-before($refe,'.')"/>
</xsl:variable>
<xsl:variable name="post">
<xsl:value-of select="substring-after($refe,'.')"/></xsl:variable>
<xsl:variable name="siz">
<xsl:choose>
<xsl:when test="$pre>'1'">
<xsl:value-of select="concat('LRSC_CH_',$pre,'/P',translate($full,'.','-'))"></xsl:value-of>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('LRSC_CH_0',$pre,'/P',translate($full,'.','-'))"></xsl:value-of>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<a href="{$siz}">
<xsl:value-of select="./toc-pg"/>
</a>
</td>
</tr>
</tbody>
</table>
<xsl:if test="./toc-subitem">
<xsl:for-each select="./toc-subitem">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:if>
<!--</table>-->
</xsl:template>
<ntw:nums num="1" word="first"/>
<ntw:nums num="2" word="second"/>
<ntw:nums num="3" word="third"/>
<ntw:nums num="4" word="forth"/>
<ntw:nums num="5" word="fifth"/>
<ntw:nums num="6" word="sixth"/>
<ntw:nums num="7" word="seventh"/>
<ntw:nums num="8" word="eighth"/>
<ntw:nums num="9" word="nighth"/>
<ntw:nums num="10" word="tenth"/>
</xsl:style-sheet>
here i've declared <xsl:when test="//section/title/content-style[upper-case(./text())=upper-case(current()/toc-title/text())]/section[1]/para[1]/#num[1]"> to get the following page num of section tag, but here it is not getting caught properly, when i make it
<xsl:when test="//section[upper-case(title/content-style/text())=upper-case(current()/toc-title/text())]/section[1]/para[1]/#num[1]">
it is throwing me an error as below.
XPTY0004: The supplied sequence ('3' item(s)) has the wrong occurrence to match the sequence type xs:string ('zero or one')
please let me know where am i going wrong and how to catch the sequence.
Thanks

This is your current expression...
<xsl:when test="//section/title/content-style[upper-case(./text())
= upper-case(current()/toc-title/text())]/section[1]/para[1]/#num[1]">
If you remove the conditional check on the toc-title it becomes this
<xsl:when test="//section/title/content-style/section[1]/para[1]/#num[1]">
This should (hopefully) highlight your problem as it is looking for a section element under the content-style object. Looking at your XML, this is not the case.
As your section element is under another section element, you possible need to nest your conditions here. Try this instead
<xsl:when test="//section[title/content-style[upper-case(text())
= upper-case(current()/toc-title/text())]]/section[1]/para[1]/#num">
There is maybe a case for using a variable here, to improve readability:
<xsl:variable name="toc-title" select="upper-case(current()/toc-title/text())" />
<xsl:choose>
<xsl:when test="//section[title/content-style[upper-case(text()) = $toc-title]]/section[1]/para[1]/#num">
Having said that, I couldn't recreate the error when I used your alternate expression.

Related

XSLT using regex pattern

I have a requirements to get the value based on a priority #schemeNames. Get the value of ID if the #schemeName='TaxNumber' is present, else if #schemeName='PassportNumber', else if #schemeName is no value. After getting the value, it needs to check or ignore the 1st 2 characters if it is Alpha. Also, I need to consider the spaces between words in #schemeName. If for example, the value of my #schemeName is 'Tax Number' or 'taxnumber' it is valid. But if the value is like this, 't axNum Ber', it should not validate this value.
Here is my XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<Result>
<xsl:for-each select="/Record/Data/ID">
<xsl:choose>
<xsl:when test="matches(lower-case(.[#schemeName]),'^tax\s+number')">
<xsl:if test="matches(substring(.,1,2),'^[a-zA-Z]+$')">
<xsl:value-of select="substring(.,3)"/>
</xsl:if>
</xsl:when>
<xsl:when test="matches(lower-case(.[#schemeName]),'^passport\s+number')">
<xsl:if test="matches(substring(.,1,2),'^[a-zA-Z]+$')">
<xsl:value-of select="substring(.,3)"/>
</xsl:if>
</xsl:when>
<xsl:when test=".[#schemeName='']">
<xsl:if test="matches(substring(.,1,2),'^[a-zA-Z]+$')">
<xsl:value-of select="substring(.,3)"/>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</Result>
</xsl:template>
</xsl:stylesheet>
INPUT:
<Record>
<Data>
<ID schemeName="TaxNumber">PT123457</ID>
<ID schemeName="PassportNumber">PT098732</ID>
<ID schemeName="LicenseNumber">PT445423</ID>
<ID schemeName="">PT7566435</ID>
</Data>
</Record>
GENERATED OUTPUT:
<Result>7566435</Result>
The output generated is coming from the #schemeName that is null. It should be coming from the TaxNumber since it is present. There's something wrong in my condition when checking the #schemeNames.
I am using XSLT v2.0. Thank you!
How about setting your priorities in variables? Something like:
<xsl:variable name="prio1" select="ID[matches(lower-case(#schemeName),'^tax\s?number')]"/>
<xsl:variable name="prio1_value">
<xsl:choose>
<xsl:when test="matches($prio1, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio1,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="prio2" select="ID[matches(lower-case(#schemeName),'^passport\s?number')]"/>
<xsl:variable name="prio2_value">
<xsl:choose>
<xsl:when test="matches($prio2, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio2,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="prio3" select="ID[#schemeName='']"/>
<xsl:variable name="prio3_value">
<xsl:choose>
<xsl:when test="matches($prio3, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio3,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio3"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
Note: I have changed \s+ to \s? to make the space optional.
Also, you can use the if-then-else construct in xslt 2.0. The final code is below:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="Record/Data"/>
</xsl:template>
<xsl:template match="Data">
<xsl:variable name="prio1" select="ID[matches(lower-case(#schemeName),'^tax\s?number')]"/>
<xsl:variable name="prio1_value">
<xsl:choose>
<xsl:when test="matches($prio1, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio1,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="prio2" select="ID[matches(lower-case(#schemeName),'^passport\s?number')]"/>
<xsl:variable name="prio2_value">
<xsl:choose>
<xsl:when test="matches($prio2, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio2,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio2"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="prio3" select="ID[#schemeName='']"/>
<xsl:variable name="prio3_value">
<xsl:choose>
<xsl:when test="matches($prio3, '^[A-z]{2}.*$')">
<xsl:value-of select="substring($prio3,3)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$prio3"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<Result>
<xsl:value-of select="if ($prio1) then ($prio1_value) else
if ($prio2) then ($prio2_value) else
if ($prio3) then ($prio3_value) else 0"/>
</Result>
</xsl:template>
</xsl:stylesheet>

xslt if not value, no row

I have this xml that needs to be transformed:
<?xml version="1.0" encoding="utf-8"?>
<racine>
<index>
<Parent nom="00000002" Name="" Address="" />
<Meter numSerie="00000002" />
<arrêté dateArrêté="28/02/2015 00:00:00">
<ValeurIndex Libelle="PMAXVALUE0">0.104</ValeurIndex>
</arrêté>
</index>
<index>
<Parent nom="00000002B" Name="" Address="" />
<Meter numSerie="" />
<arrêté dateArrêté="28/02/2015 00:00:00">
<ValeurIndex Libelle="R1INDEX0">3.754</ValeurIndex>
<ValeurIndex Libelle="PMAXVALUE0">1.047</ValeurIndex>
</arrêté>
</index>
</racine>
The xslt that make the transformation is:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="ISO-8859-1"/>
<!-- Parcours des noeuds "racine/index" -->
<xsl:variable name="v_separateur">
<xsl:text>,</xsl:text>
</xsl:variable>
<!-- sort by date desc" -->
<xsl:template match="/racine">
<xsl:apply-templates select="index">
<xsl:sort select="arrêté/#dateArrêté" order="descending" data-type="number"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="index">
<!-- get repeating values once -->
<xsl:variable name="constants">
<!-- SP_ID -->
<xsl:value-of select="Parent/#nom"/>
<xsl:value-of select="$v_separateur"/>
<!-- METER_NUMBER-->
<xsl:value-of select="Meter/#numSerie"/>
<xsl:value-of select="$v_separateur"/>
<!-- DATE & TIME-->
<xsl:value-of select="arrêté/#dateArrêté"/>
<xsl:value-of select="$v_separateur"/>
</xsl:variable>
<!-- Only Process OBIS* values ignore other -->
<xsl:apply-templates select="arrêté/ValeurIndex[
#Libelle='EA.R00'
or #Libelle='EA.R01'
or #Libelle='EA.R02'
or #Libelle='EA.R03'
or #Libelle='EA.R05'
or #Libelle='EA.R06'
or #Libelle='EA.R07'
or #Libelle='EAE.R00'
or #Libelle='AEINDEX0'
or #Libelle='AEINDEX1'
or #Libelle='AEINDEX2'
or #Libelle='AEINDEX3'
or #Libelle='AEINDEX5'
or #Libelle='AEINDEX6'
or #Libelle='AEINDEX7'
or #Libelle='R1INDEX0'
or #Libelle='PMAXVALUE0'
]">
<xsl:with-param name="constants" select="$constants"/>
</xsl:apply-templates>
<!-- ADD NEW ROW -->
<xsl:value-of select="$constants"/>
<xsl:text>KWH</xsl:text>
<xsl:value-of select="$v_separateur"/>
<xsl:value-of select="$v_separateur"/>
<xsl:choose>
<xsl:when test="arrêté/ValeurIndex[#Libelle='EA.R00'] > arrêté/ValeurIndex[#Libelle='EA.R02']">
<xsl:value-of select="arrêté/ValeurIndex[#Libelle='EA.R00']"/>
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="arrêté/ValeurIndex[#Libelle='EA.R02']"/>
<xsl:text>
</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="ValeurIndex"> <!--match="ValeurIndex"-->
<xsl:param name="constants"/>
<xsl:value-of select="$constants"/>
<xsl:choose>
<xsl:when test="#Libelle = 'EA.R00'">KWH,PUNTA</xsl:when>
<xsl:when test="#Libelle = 'EA.R01'">KWH,VALLE</xsl:when>
<xsl:when test="#Libelle = 'EA.R02'">KWH,LLANO</xsl:when>
<xsl:when test="#Libelle = 'EA.R03'">KW,</xsl:when>
<xsl:when test="#Libelle = 'EA.R05'">KWH,</xsl:when>
<xsl:when test="#Libelle = 'EA.R06'">KVH,ER_Q2</xsl:when>
<xsl:when test="#Libelle = 'EA.R07'">KVH,ER_Q3</xsl:when>
<xsl:when test="#Libelle = 'EAE.R00'">KVH,ER_Q4</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX0'">KWH,PUNTA_SA</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX1'">KWH,VALLE_SA</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX2'">KWH,LLANO_SA</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX3'">KWH,</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX5'">KWH,ENERSAL</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX6'">KW,PUNTA</xsl:when>
<xsl:when test="#Libelle = 'AEINDEX7'">KW,VALLE</xsl:when>
<xsl:when test="#Libelle = 'R1INDEX0'">KW,LLANO</xsl:when>
<xsl:when test="#Libelle = 'PMAXVALUE0'">KW, PUNTA_SA</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Param[#code = 'TYPE_EQP']/#value"/>
</xsl:otherwise>
</xsl:choose>
<xsl:value-of select="$v_separateur"/>
<xsl:value-of select="."/>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I want to have just the lines that we have some value, so in this case:
00000002,00000002,28/02/2015 00:00:00,KW, PUNTA_SA,0.104
00000002B,,28/02/2015 00:00:00,KW,LLANO,3.754
00000002B,,28/02/2015 00:00:00,KW, PUNTA_SA,1.047
But as we put the maximum of EA.R00 and EA.R02 I will have a row without date and without data. I want that in case that both values dont exist dont write anything. As the xslt is right now, I will obtain:
00000002,00000002,28/02/2015 00:00:00,KW, PUNTA_SA,0.104
00000002,00000002,28/02/2015 00:00:00,KWH,,
00000002B,,28/02/2015 00:00:00,KW,LLANO,3.754
00000002B,,28/02/2015 00:00:00,KW, PUNTA_SA,1.047
00000002B,,28/02/2015 00:00:00,KWH,,
(I dont want to see the 2nd and 5th row)
Thanks
The extra lines your refer to are output by the code after the comment <!-- ADD NEW ROW -->. What you can do is wrap this code in an xsl:if to check if either EA.R00 or EA.R02 exists.
Try this:
<!-- ADD NEW ROW -->
<xsl:if test="arrêté/ValeurIndex[#Libelle='EA.R00' or #Libelle='EA.R02']">
<xsl:value-of select="$constants"/>
<xsl:text>KWH</xsl:text>
<xsl:value-of select="$v_separateur"/>
<xsl:value-of select="$v_separateur"/>
<xsl:choose>
<xsl:when test="arrêté/ValeurIndex[#Libelle='EA.R00'] > arrêté/ValeurIndex[#Libelle='EA.R02']">
<xsl:value-of select="arrêté/ValeurIndex[#Libelle='EA.R00']"/>
<xsl:text>
</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="arrêté/ValeurIndex[#Libelle='EA.R02']"/>
<xsl:text>
</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:if>

xsl choose in concat

I have the following data:
XML
<team>
<rectx>30</rectx>
<diadata>
<bestAnd>-350</bestAnd>
</diadata>
<diadata>
<bestAnd>-250</bestAnd>
</diadata>
<diadata>
<bestAnd>-50</bestAnd>
</diadata>
</team>
XSL
<xsl:variable name="list">
<xsl:value-of select="'M'" />
<xsl:for-each select="/team/diadata/bestAnd">
<xsl:choose>
<xsl:when test=". <0">
<xsl:value-of select=".*-1+400" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="." />
</xsl:otherwise>
</xsl:choose>
<xsl:variable name="position" select="position()" />
<xsl:value-of select="concat(/team/rectx*$position+40,' ',.,' L')" />
</xsl:for-each>
</xsl:variable>
<xsl:variable name="finallist">
<xsl:value-of select="substring($list, 1, string-length($list) - 2)" />
</xsl:variable>
<text x="250" y="50"
style="font-family: Arial;
font-size : 24;
stroke : #000000;
fill : #000000;">
<xsl:value-of select="$finallist" />
</text>
The output has to be
M70 750 L100 650 L130 450
however with the choose statement it is
M75070 -350 L650100 -250 L450130 -50
so it does
"letter""y-val after calc""x-val" "y-val"
I can't understand why the concat does not work with the choose statement but without it works great. Prob is that I can't have negative numbers but instead need to take those and convert them to positive (*-1) and add 400.
Any ideas?
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="list">
<xsl:value-of select="'M'"/>
<xsl:for-each select="/team/diadata/bestAnd">
<xsl:variable name="position" select="position()"/>
<xsl:value-of select="concat(/team/rectx*$position+40,' ')"/>
<xsl:choose>
<xsl:when test=". <0">
<xsl:value-of select=".*-1+400"/>
<xsl:value-of select="' L'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
</xsl:template>
</xsl:stylesheet>

Default Namespace Issue during translation using xsl

<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.

XSLT Confusion with xsl:apply-templates

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