Grouping by result of sum - xslt

I'm converting tables for a client and some elements need to span across multiple columns. Each element has the attribute aid:ccols which indicates across how many columns this value should span. I'm trying to group these elements until the sum of aid:ccols equals basictable/#aid:tcols and so on.
I tried multiple things by using xsl:for-each, group-by but nothing seems to work.
<basictable xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/" aid:table="table" aid:trows="7" aid:tcols="3">
<cell-tab-tit-center aid:table="cell" aid:crows="1" aid:ccols="3">1. Les « salaires » du mois</cell-tab-tit-center>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="67.53149606308261">Salaire mensuel</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="2">Arrêté à la date de rupture du contrat (fin du préavis, même en cas de dispense par l’employeur).</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="67.53149606308261">Rappels éventuels</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="2">Vérifier si des rappels restent dus.</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="67.53149606308261">Primes annuelles</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="2">Vérifier si les primes annuelles sont dues au prorata.</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="67.53149606308261">Ind. comp. cp N-1</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="147.40157480314957">Contrôler le solde de cp.</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="248.94881889754743">
comparaison maintien/10<superscript>e</superscript>
rém. de la période de réf. N-1.
</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="67.53149606308261">Ind. comp. cp en cours</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="147.40157480314957">Calculer le droit, au réel + règle des équivalences, jusqu’à la fin du préavis.</cell-tab-txt-left>
<cell-tab-txt-left aid:table="cell" aid:crows="1" aid:ccols="1" aid:ccolwidth="248.94881889754743">
comparaison maintien/10<superscript>e</superscript>
rém. de la période en cours et jusqu’à la fin du préavis.
</cell-tab-txt-left>
<cell-tab-subtit-left aid:table="cell" aid:crows="1" aid:ccols="3">
<b>Permet d’obtenir le total du mois représentant du salaire</b>
</cell-tab-subtit-left>
</basictable>
The result should be
<table>
<tr>
<th colspan="3">1. Les « salaires » du mois</th>
</tr>
<tr>
<td>Salaire mensuel</td>
<td>Arrêté à la date de rupture du contrat (fin du préavis, même en cas de dispense par l’employeur).</td>
</tr>
<tr>
<td>Rappels éventuels</td>
<td>Vérifier si des rappels restent dus.</td>
</tr>
<tr>
<td>Primes annuelles</td>
<td>Vérifier si les primes annuelles sont dues au prorata.</td>
</tr>
<tr>
<td>Ind. comp. cp N-1</td>
<td>Contrôler le solde de cp.</td>
<td>
comparaison maintien/10
<superscript xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">e</superscript>
rém. de la période de réf. N-1.
</td>
</tr>
<tr>
<td>Ind. comp. cp en cours</td>
<td>Calculer le droit, au réel + règle des équivalences, jusqu’à la fin du préavis.</td>
<td>
comparaison maintien/10
<superscript xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/">e</superscript>
rém. de la période en cours et jusqu’à la fin du préavis.
</td>
</tr>
.
.
.
</table>
My code:
<xsl:template match="cell-tab-txt-right | cell-tab-subtit-left | cell-tab-txt-center | cell-tab-txt-left | cell-tab-subtit-right | cell-tab-subtit-center | cell-tab-tit-center | cell-tab-tit-right | cell-tab-tit-left">
<xsl:param name="columns" tunnel="yes"/>
<xsl:if test="$columns != 0">
<xsl:choose>
<xsl:when test="#aid:ccols = $columns">
<xsl:element name="tr">
<xsl:element name="th">
<xsl:attribute name="colspan"><xsl:value-of select="#aid:ccols"></xsl:value-of></xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="tr">
<xsl:apply-templates select=".|following-sibling::*[1][position() + (#aid:ccols - 1) $lt; $columns]" mode="list"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>

At https://xsltfiddle.liberty-development.net/bFN1yaa/2 I have tried to convert the xsl:iterate example from the comment to sibling recursion:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:aid="http://ns.adobe.com/AdobeInDesign/4.0/"
exclude-result-prefixes="#all"
version="2.0">
<xsl:output method="html" indent="yes" version="5"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="basictable">
<table>
<xsl:variable name="max-cols" select="xs:integer(#aid:tcols)"/>
<xsl:apply-templates select="*[1]" mode="row">
<xsl:with-param name="max-cols" select="$max-cols"/>
</xsl:apply-templates>
</table>
</xsl:template>
<xsl:template match="basictable/*" mode="row">
<xsl:param name="max-cols"/>
<xsl:param name="cells" select="()"/>
<xsl:variable name="current-cells" select="$cells, ."/>
<xsl:variable name="sum-cells" select="sum($current-cells/#aid:ccols)"/>
<xsl:if test="$sum-cells eq $max-cols">
<tr>
<xsl:apply-templates select="$current-cells"/>
</tr>
</xsl:if>
<xsl:apply-templates select="following-sibling::*[1]" mode="row">
<xsl:with-param name="cells" select="if ($sum-cells eq $max-cols) then () else $current-cells"/>
<xsl:with-param name="max-cols" select="$max-cols"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="basictable/*">
<td>
<xsl:apply-templates/>
</td>
</xsl:template>
</xsl:stylesheet>
I think the grouping of the children of basictable into tr works the same as the xsl:iterate sample, in both samples I have not tried to implement the use of colspan and th cells as I am not sure what determines that.

Related

How to keep track of position from a template to a different template (2)?

Follow on question to: https://stackoverflow.com/questions/71635891/how-to-keep-track-of-position-from-a-template-to-a-different-template?noredirect=1#comment126614972_71635891
My new problem is, there could be more than one simplePath in a jump and I want all simplePath inside a jump to start
from the same position. My current is issue is that I'm not competent enough to translate my current idea into XSL, I added in comment in the XSLT code what I'm trying to achieve
D --- E --- F K --- L --- M --- N --- O
/ \ /
A --- B --- C--- / \ -- J ---/
\ / \
\ / \
G --- H --- I Q --- R --- S
<root>
<simplePath>
<point>A</point>
<point>B</point>
<point>C</point>
</simplePath>
<jump>
<simplePath>
<point>D</point>
<point>E</point>
<point>F</point>
</simplePath>
<simplePath>
<point>G</point>
<point>H</point>
<point>I</point>
</simplePath>
</jump>
<simplePath>
<point>J</point>
</simplePath>
</root>
expected output
A : 0
B : 50
C : 100
D : 300
E : 350
F : 400
Dbis : 300
Ebis : 350
Fbis : 400
G : 600
poor attempt :
<xsl:template match="/root">
<xsl:call-template name="process">
<xsl:with-param name="points" select=".//point"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="process">
<xsl:param name="points" />
<xsl:param name="total" select="0"/>
<xsl:param name="savePos" select="0"/>
<!-- new param -->
<!-- output -->
<xsl:value-of select="boolean($points[1]/ancestor::jump)"/>
<xsl:value-of select="$points[1]"/>
<xsl:text> : </xsl:text>
<xsl:value-of select="$total"/>
<!-- recursive call -->
<xsl:if test="count($points) > 1">
<xsl:text>
</xsl:text>
<xsl:call-template name="process">
<xsl:with-param name="points" select="$points[position() > 1]"/>
<xsl:with-param name="total" select="if(boolean($points[1]/ancestor::jump) != boolean($points[2]/ancestor::jump)) then $total + 200 else $total + 50"/>
<!-- my "attempt" -->
<!-- I want to save the pos of total IF it's the first point of the first simplePath in a Jump -->
<xsl:with-param name="savePos" select=""/>
<!-- Next, I will add a new "if condition" here
<xsl:with-param name="total" select="if(boolean($points[1]/ancestor::jump) != boolean($points[2]/ancestor::jump))
then
>>>>if I'm not in the first simplePath of "jump", and it's the first "point" of this "simplePath" then
$total = $savePos
else
$total + 200
else
$total + 50"/>
- -->
</xsl:call-template>
</xsl:if>
</xsl:template>

Aggregation with XSLT

I have the target /aggregate-rating.xml
<aggregate>
<rating>
<issuerNumber>388d</issuerNumber>
<WAABCA>baa1</WAABCA>
<WAABCANumeric>14.2</WAABCANumeric>
<WANotches>3.4</WANotches>
<WALTRatingNumeric>17.6</WALTRatingNumeric>
</rating>
<rating>
<issuerNumber>89f8</issuerNumber>
<WAABCA>b2</WAABCA>
<WAABCANumeric>7.4</WAABCANumeric>
<WANotches>-1.6</WANotches>
<WALTRatingNumeric>5.8</WALTRatingNumeric>
</rating>
===================================
</aggregate>
Mapping /rating-chart.xml
<ratings>
<rating MD="Aaa" SP="AAA" Grade="Investment" rank="1"/>
==================================
<rating MD="A1" SP="A+" Grade="Investment" rank="5"/>
<rating MD="A2" SP="A" Grade="Investment" rank="6"/>
<rating MD="A3" SP="A-" Grade="Investment" rank="7"/>
<rating MD="Baa1" SP="BBB+" Grade="Investment" rank="8"/>
========================
<rating MD="B2" SP="B" Grade="Non-Investment" rank="15"/>
<rating MD="B3" SP="B-" Grade="Non-Investment" rank="16"/>
<rating MD="Caa1" SP="CCC" Grade="Non-Investment" rank="17"/>
====================================
<rating MD="C" Grade="Non-Investment" rank="21"/>
</ratings>
The scale is based on WANotches. e.g issuer 388d, its WAABCA is baa1 (rank 8) then it notches 3.4 (round to 3), its rank is boosted to 5. The adjusted rating will be <rating MD="A1" SP="A+" Grade="Investment" rank="5"/>
Expected result:
<aggregate>
<rating>
<issuerNumber>388d</issuerNumber>
<WAABCA>baa1</WAABCA>
<WAABCANumeric>14.2</WAABCANumeric>
<WANotches>3.4</WANotches>
<WALTRatingNumeric>17.6</WALTRatingNumeric>
<adjustedMoody>A1</adjustedMoody>
<adjustedStandardPoor>A+</adjustedStandardPoor>
<adjustedGrade>Investment</adjustedGrade>
</rating>
<rating>
<issuerNumber>89f8</issuerNumber>
<WAABCA>b2</WAABCA>
<WAABCANumeric>7.4</WAABCANumeric>
<WANotches>-1.6</WANotches>
<WALTRatingNumeric>5.8</WALTRatingNumeric>
<adjustedMoody>Caa1</adjustedMoody>
<adjustedStandardPoor>CCC</adjustedStandardPoor>
<adjustedGrade>Non-Investment</adjustedGrade>
</rating>
=======================================
</aggregate>
My xsl:
<xsl:variable name="ratingChart" select="doc('/rating-chart.xml')"/>
<xsl:template match="rating">
<xsl:variable name="notch" select="round(WANotches)"/>
<xsl:variable name="currentRank" select="$ratingChart/ratings/rating[upper-case(#MD) eq upper-case(WAABCA)]/#rank"/>
<xsl:variable name="notchRank" select="$currentRank - $notch"/>
<xsl:variable name="aggRank" select="$ratingChart/ratings/rating[#rank = $notchRank]"/>
<xsl:variable name="adjustedMD" select="$aggRank/#MD"/>
<xsl:variable name="adjustedSP" select="$aggRank/#SP"/>
<xsl:variable name="adjustedGrade" select="$aggRank/#Grade"/>
<xsl:copy>
<xsl:sequence select="$aggRank"/>
<xsl:apply-templates/>
<xsl:call-template name="aggrRating">
<xsl:with-param name="aMD" select="$adjustedMD"/>
<xsl:with-param name="aSP" select="$adjustedSP"/>
<xsl:with-param name="aGrade" select="$adjustedGrade"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="aggrRating">
<xsl:param name="aMD"/>
<xsl:param name="aSP"/>
<xsl:param name="aGrade"/>
<adjustedMoody><xsl:value-of select="$aMD"/></adjustedMoody>
<adjustedStandardPoor><xsl:value-of select="$aSP"/></adjustedStandardPoor>
<adjustedGrade><xsl:value-of select="$aGrade"/></adjustedGrade>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
I got all the blank elements : <adjustedMoody>, <adjustedStandardPoor>, <adjustedGrade>.
How can I fix my xsl?

Multiplying two variables in XSLT-1

I have tried for hours to multiply 2 varibales in XSLT1 but I can't seem to figure it out.
The result shows in excel as NaN
I have searched for a while but I'm having trouble with this, just started using XSLT
Variables:
Weight = 10
Length = 12
XSLT:
<xsl:variable name ="content"><xsl:value-of select="$length * $weight" /></xsl:variable>
EDIT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rvmon="rosenbergverft.com:3D/2017/WeightMTO" xmlns:pdms="rosenbergverft.com:3D/2010/Models">
<xsl:output method="text" omit-xml-declaration="yes" standalone="no" media-type="text/xls" />
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." />
<xsl:template match="/">Building block;Discipline;Area;Sub. Area;Syst. no.;Weight Item no.;Piecemark no.;Weight Item Descr.;CompType;Type code;Rating or Scedule;Spec.;Dim. (");Material;Cost Code COR;Weight Phase Code;Mod. Phase Code;Weight Status % (allow.);Mod. Constr. Code;Mod. Handl. Code;No. off;Unit Length/ Area (m,m2, m3);Unit Weight (kg/m, m2, m3);Unit Weight MON(kg/m, m2, m3);Net Dry Weight (kg);Gross Dry Weight (kg);Content Weight (kg);Installed weight;CoG East;CoG North;CoG Elevation;Ref. doc., dwg., P&ID etc.;Remarks;Cost for instrument valves [NOK];install code;MON Lift Code;Paint Surface;Insulation Class;
<xsl:for-each select="/rvmon:WeightMTO/rvmon:MTOOwner"><xsl:for-each select="rvmon:Piecemark/rvmon:WeightItemNo/rvmon:Part">
<xsl:variable name= "weight" select="format-number(rvmon:ContentWeight/#number, '#0,0##', 'euro')" />
<xsl:variable name="length"><xsl:choose><xsl:when test="contains(rvmon:CompType,'BOLT')"><xsl:text> 1 </xsl:text></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000, '#0,0##', 'euro')" /></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm2'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000000, '#0,0##', 'euro')" /></xsl:when><xsl:when test="rvmon:UnitLength/#unit = 'mm3'"><xsl:value-of select="format-number(rvmon:UnitLength/#number div 1000000000, '#0,0##', 'euro')" /></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:UnitLength/#number, '#0,0##', 'euro')" /></xsl:otherwise></xsl:choose></xsl:variable>
<xsl:variable name="content" select="$length * $weight" />
<xsl:value-of select="../../../rvmon:BuildingBlock" />;<xsl:value-of select="rvmon:Discipline" />;<xsl:value-of select="../../../rvmon:Module" />;<xsl:value-of select="../../../rvmon:SubArea" />;<xsl:value-of select="../../../rvmon:SystNo" />;<xsl:value-of select="rvmon:WeightItemNo" />;<xsl:value-of select="rvmon:Piecemark" />;<xsl:value-of select="rvmon:WeightItemDescr" />;<xsl:value-of select="rvmon:CompType" />;<xsl:value-of select="rvmon:TypeCode" />;<xsl:value-of select="rvmon:Rating" />;<xsl:value-of select="rvmon:Spec" />;<xsl:choose><xsl:when test="rvmon:Discipline = 'L'"><xsl:value-of select="format-number(rvmon:Dim/#number, '#0,##', 'euro')" /><xsl:choose><xsl:when test="rvmon:Dim/#unit = 'inch'">"</xsl:when><xsl:otherwise><xsl:value-of select="rvmon:Dim/#unit" /></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="rvmon:Discipline = 'N'"></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:Dim/#number, '#0,##', 'euro')" /><xsl:value-of select="rvmon:Dim/#unit" /></xsl:otherwise></xsl:choose>;<xsl:value-of select="rvmon:Material" />;<xsl:value-of select="rvmon:CostCodeCOR" />;<xsl:value-of select="rvmon:WeightPhaseCode" />;<xsl:value-of select="rvmon:ModPhaseCode" />;<xsl:value-of select="format-number(rvmon:WeightStatus/#number * 100, '00', 'euro')" />%;<xsl:value-of select="rvmon:ModConstrCode" />;<xsl:value-of select="rvmon:ModHandlCode" />;<xsl:value-of select="format-number(rvmon:NoOff/#number, '#0,###', 'euro')" />;<xsl:value-of select="$length"/>;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="format-number(rvmon:UnitWeight/#number, '#0,0##', 'euro')" />;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="format-number(rvmon:MONUnitWeightFactor/#number, '#0,0#####', 'euro')" />;<xsl:choose><xsl:when test="contains(rvmon:CompType,'BOLT')"><xsl:text> 1 </xsl:text></xsl:when><xsl:otherwise><xsl:value-of select="format-number(rvmon:NetDryWeight/#number, '#0,0##', 'euro')" /></xsl:otherwise></xsl:choose>;<xsl:value-of select="format-number(rvmon:AllowanceWeight/#number, '#0,0##', 'euro')" />;<xsl:if test="rvmon:ModHandlCode = 'RP'">-</xsl:if><xsl:value-of select="$weight"/>;<xsl:if test="rvmon:ProdStatus ='ABC' "><xsl:text> Yes </xsl:text></xsl:if>;<xsl:value-of select="format-number(rvmon:CoGEast/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="format-number(rvmon:CoGNorth/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="format-number(rvmon:CoGElevation/#number div 1000, '#0,0##', 'euro')" />;<xsl:value-of select="../../../rvmon:DrawNumber" />;<!-- xsl:value-of select="rvmon:Remarks" / --><xsl:value-of select="../../../pdms:PDMSElement/pdms:ElementName/#text" />;;;;<xsl:value-of select="format-number(rvmon:PaintSurface/#number div 1000000, '#0,0##', 'euro')" />;<xsl:value-of select="../../../rvmon:InsulationClass" />;<xsl:value-of select="$length"/>;<xsl:value-of select="$content"/><xsl:text>
</xsl:text></xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
XML-document
<UnitLength number="1.000" unit="pcs" field="Quantity" />
<ContentWeight number="8.005" unit="kg" field="ContentWeight" /> />
I am able to output "weight" and "length" by itself. But I cant even do
"weight * 10"
Sorry if it is messy.
You need to remove all formatting number while assigning the variable and while multipled result need to format number like below:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:rvmon="rosenbergverft.com:3D/2017/WeightMTO"
exclude-result-prefixes="#all"
version="1.0">
<xsl:decimal-format name="euro" decimal-separator="," grouping-separator="." />
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:variable name= "weight" select="//rvmon:ContentWeight/#number" />
<xsl:variable name="length">
<xsl:choose>
<xsl:when test="contains(//rvmon:CompType,'BOLT')">
<xsl:text>1</xsl:text>
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000" />
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm2'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000000" />
</xsl:when>
<xsl:when test="rvmon:UnitLength/#unit = 'mm3'">
<xsl:value-of select="//rvmon:UnitLength/#number div 1000000000" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="//rvmon:UnitLength/#number" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="content" select="format-number(($weight * $length), '#0,0##', 'euro')" />
<xsl:value-of select="$content"/>
</xsl:template>
</xsl:stylesheet>
You have:
<xsl:variable name= "weight" select="format-number(rvmon:ContentWeight/#number, '#0,0##', 'euro')" />
A number formatted to use a decimal comma is no longer a number for the purposes of XPath/XSLT. A number can contain only digits and a decimal period.
Assuming that the original values (not shown in your question) are true numbers, use them for the multiplication, and format them only for the output.

Filtering using xslt for specific node values

I need to filter huge and redundant xml file.
Easy thing is to eliminate all nodes with no attributes and no content:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:if test=". != '' or ./#* != ''">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
but i also need to filter out nodes containing
<type>0</type>
nodes containing only
<whatever id="-1 />
and nodes containing only empty attributes like:
<dateacquired year="" month="" day="" long="" unformatted=""/>
an excerpt of my (machine generated) input file is:
<record table="book" id="1">
<bookdata>
<bookid unformatted="1">1</bookid>
<marked bool="False">No</marked>
<lastmodified year="2013" month="09" day="25" long="Wednesday, September 25, 2013" unformatted="20130925">09/25/2013</lastmodified>
<title>Intervista Col Vampiro</title>
<fulltitle>Ciclo Dei Vampiri: Intervista Col Vampiro</fulltitle>
<fulltitle2>Intervista Col Vampiro (Ciclo Dei Vampiri)</fulltitle2>
<referenceno>BB00001</referenceno>
<publishdate year="1993" month="" day="" long="1993" unformatted="1993">1993</publish date>
<copyrightdate year="" month="" day="" long="" unformatted=""/>
<type id="-1"/>
<authors sort="Rice, Anne">
<author id="1">
<name>Anne Rice</name>
<sortby>Rice, Anne</sortby>
<roles/>
</author>
</authors>
<credits/>
<image1>
<filename>Book_1_3.jpg</filename>
<type>2</type>
<notes/>
</image1>
<image2>
<filename/>
<type>0</type>
<notes/>
</image2>
<image3>
<filename/>
<type>0</type>
<notes/>
</image3>
<image4>
<filename/>
<type>0</type>
<notes/>
</image4>
<image5>
<filename/>
<type>0</type>
<notes/>
</image5>
<image6>
<filename/>
<type>0</type>
<notes/>
</image6>
<image7>
<filename/>
<type>0</type>
<notes/>
</image7>
<image8>
<filename/>
<type>0</type>
<notes/>
</image8>
<image9>
<filename/>
<type>0</type>
<notes/>
</image9>
<subtitle/>
<titlesort>Intervista Col Vampiro</titlesort>
<publisher id="1">Salani</publisher>
<publicationplace id="-1"/>
<isbn/>
<lccn/>
<lccallnum/>
<dewey>823.9</dewey>
<country id="-1"/>
<pages unformatted="283">283</pages>
<numberofsections unformatted="0">0</numberofsections>
<printedby id="-1"/>
<binding id="-1"/>
<edition id="1">Ebook</edition>
<printing id="-1"/>
<language id="-1"/>
<series id="1">Ciclo Dei Vampiri</series>
<releaseno unformatted="0">0</releaseno>
<originaltitle>Interview With The Vampire</originaltitle>
<originalsubtitle/>
<originalpublisher id="-1"/>
<originalcountry id="-1"/>
<originallanguage id="-1"/>
<originalcopyright year="1976" month="" day="" long="1976" unformatted="1976">1976</originalcopyright>
<price integer="8" fraction="0" unformatted="8.0">8.00</price>
<value integer="0" fraction="0" unformatted="0.0">0.00</value>
<sellingprice integer="0" fraction="0" unformatted="0.0">0.00</sellingprice>
<changeinvalue>0.00</changeinvalue>
<changeinvaluepr>0.00</changeinvaluepr>
<condition id="-1"/>
<appraiser id="-1"/>
<insurance id="-1"/>
<registered year="2005" month="09" day="10" long="Saturday, September 10, 2005" unformatted="20050910">09/10/2005</registered>
<status id="-1"/>
<dateacquired year="" month="" day="" long="" unformatted=""/>
<acquiredfrom id="-1"/>
<personalrating id="-1"/>
<category id="1">Horror-Gotico</category>
<subcategory id="-1"/>
<owner id="-1"/>
<location id="-1"/>
<keywords>
<keyword id="1">Vampiro</keyword>
<keyword id="2">Vampiri</keyword>
</keywords>
<newbook bool="False">No</newbook>
<onloan bool="False">No</onloan>
<overdue bool="False">No</overdue>
<borrower id="-1"/>
<borrowercategory id="-1"/>
<dateborrowed year="" month="" day="" long="" unformatted=""/>
<datedue year="" month="" day="" long="" unformatted=""/>
<reserved bool="False">No</reserved>
<reservedto id="-1"/>
<reserveddate year="" month="" day="" long="" unformatted=""/>
<awards/>
<awardyear/>
<awarddetails/>
<nominations/>
<nominationyear/>
<nominationdetails/>
<custom01/>
<custom02/>
<custom03>http://www.ddunlimited.net/viewtopic.php?f=1079&t=3749847</custom03>
<custom04/>
<custom05 id="-1"/>
<custom06 id="-1"/>
<custom07 id="-1"/>
<custom08 id="-1"/>
<custom09 year="" month="" day="" long="" unformatted=""/>
<custom10 integer="0" fraction="0" unformatted="0.0">0.00</custom10>
<custom11 bool="True">Yes</custom11>
<custom12 bool="False">No</custom12>
<custom13 bool="False">No</custom13>
<custom14 bool="True">Yes</custom14>
<custom15 bool="False">No</custom15>
<custom16 bool="False">No</custom16>
<custom17 bool="False">No</custom17>
<custom18 bool="False">No</custom18>
<notes>ed2k://|file|eBook.ITA.001.Anne.Rice.Intervista.Col.Vampiro.(doc.lit.pdf.rtf).[Hyps].rar|1998285|81D4C283C03E5787170A33C335577533|/</notes>
<synopsis>A San Francisco alle soglie del 2000 il giornalista Mallory viene avvicinato da Louis De Point Du Lac, vampiro dal 1791, quando era un proprietario terriero presso New Orleans. Ridotto alla disperazione per la perdita della moglie e della figlioletta vieneiniziato alla sua tenebrosa e ferina esistenza da Lestat, collega di origini parigine, che cerca invano di far superare al discepolo l&apos;innata repulsione per l&apos;omicidio. Invano Louis si ciba di sangue di ratti e galline, e fà fuggire i servi incendiando la casa. Ormai Lestat lo domina e lo coinvolge in efferate uccisioni di innocenti. Una bimba orfana, Claudia, viene "adottata" dai due e si rivela feroce quant&apos;altri mai.</synopsis>
<reviews/>
<weblinks/>
<weblinktype id="1"/>
<filelinks/>
<filelinktype id="1"/>
<barcode/>
<originalseries id="-1"/>
<originalreleaseno unformatted="0">0</originalreleaseno>
<readhistory/>
<lastread year="" month="" day="" long="" unformatted=""/>
<readcount unformatted="0">0</readcount>
<dustjacketcondition id="-1"/>
<dimensions_width integer="0" fraction="0" unformatted="0.0">0.00</dimensions_width>
<dimensions_height integer="0" fraction="0" unformatted="0.0">0.00</dimensions_height>
<dimensions_depth integer="0" fraction="0" unformatted="0.0">0.00</dimensions_depth>
<coverprice integer="0" fraction="0" unformatted="0.0">0.00</coverprice>
<coverprice_currency id="-1"/>
<booklinks/>
</bookdata>
<contentsdata items="0"/>
</record>
desired output would be:
<record table="book" id="1">
<bookdata>
<bookid unformatted="1">1</bookid>
<marked bool="False">No</marked>
<lastmodified year="2013" month="09" day="25" long="Wednesday, September 25, 2013" unformatted="20130925">09/25/2013</lastmodified>
<title>Intervista Col Vampiro</title>
<fulltitle>Ciclo Dei Vampiri: Intervista Col Vampiro</fulltitle>
<fulltitle2>Intervista Col Vampiro (Ciclo Dei Vampiri)</fulltitle2>
<referenceno>BB00001</referenceno>
<publishdate year="1993" month="" day="" long="1993" unformatted="1993">1993</publish date>
<authors sort="Rice, Anne">
<author id="1">
<name>Anne Rice</name>
<sortby>Rice, Anne</sortby>
</author>
</authors>
<image1>
<filename>Book_1_3.jpg</filename>
<type>2</type>
</image1>
<titlesort>Intervista Col Vampiro</titlesort>
<publisher id="1">Salani</publisher>
<dewey>823.9</dewey>
<pages unformatted="283">283</pages>
<numberofsections unformatted="0">0</numberofsections>
<edition id="1">Ebook</edition>
<series id="1">Ciclo Dei Vampiri</series>
<releaseno unformatted="0">0</releaseno>
<originaltitle>Interview With The Vampire</originaltitle>
<originalcopyright year="1976" month="" day="" long="1976" unformatted="1976">1976</originalcopyright>
<price integer="8" fraction="0" unformatted="8.0">8.00</price>
<value integer="0" fraction="0" unformatted="0.0">0.00</value>
<sellingprice integer="0" fraction="0" unformatted="0.0">0.00</sellingprice>
<changeinvalue>0.00</changeinvalue>
<changeinvaluepr>0.00</changeinvaluepr>
<registered year="2005" month="09" day="10" long="Saturday, September 10, 2005" unformatted="20050910">09/10/2005</registered>
<category id="1">Horror-Gotico</category>
<keywords>
<keyword id="1">Vampiro</keyword>
<keyword id="2">Vampiri</keyword>
</keywords>
<newbook bool="False">No</newbook>
<onloan bool="False">No</onloan>
<overdue bool="False">No</overdue>
<reserved bool="False">No</reserved>
<custom03>http://www.ddunlimited.net/viewtopic.php?f=1079&t=3749847</custom03>
<custom10 integer="0" fraction="0" unformatted="0.0">0.00</custom10>
<custom11 bool="True">Yes</custom11>
<custom12 bool="False">No</custom12>
<custom13 bool="False">No</custom13>
<custom14 bool="True">Yes</custom14>
<custom15 bool="False">No</custom15>
<custom16 bool="False">No</custom16>
<custom17 bool="False">No</custom17>
<custom18 bool="False">No</custom18>
<notes>ed2k://|file|eBook.ITA.001.Anne.Rice.Intervista.Col.Vampiro.(doc.lit.pdf.rtf).[Hyps].rar|1998285|81D4C283C03E5787170A33C335577533|/</notes>
<synopsis>A San Francisco alle soglie del 2000 il giornalista Mallory viene avvicinato da Louis De Point Du Lac, vampiro dal 1791, quando era un proprietario terriero presso New Orleans. Ridotto alla disperazione per la perdita della moglie e della figlioletta vieneiniziato alla sua tenebrosa e ferina esistenza da Lestat, collega di origini parigine, che cerca invano di far superare al discepolo l&apos;innata repulsione per l&apos;omicidio. Invano Louis si ciba di sangue di ratti e galline, e fà fuggire i servi incendiando la casa. Ormai Lestat lo domina e lo coinvolge in efferate uccisioni di innocenti. Una bimba orfana, Claudia, viene "adottata" dai due e si rivela feroce quant&apos;altri mai.</synopsis>
<weblinktype id="1"/>
<filelinktype id="1"/>
<originalreleaseno unformatted="0">0</originalreleaseno>
<readcount unformatted="0">0</readcount>
<dimensions_width integer="0" fraction="0" unformatted="0.0">0.00</dimensions_width>
<dimensions_height integer="0" fraction="0" unformatted="0.0">0.00</dimensions_height>
<dimensions_depth integer="0" fraction="0" unformatted="0.0">0.00</dimensions_depth>
<coverprice integer="0" fraction="0" unformatted="0.0">0.00</coverprice>
</bookdata>
<contentsdata items="0"/>
</record>
Problem is I do not really grok transformations and, while I tried to read about them, I didn't find a comprehensible tutorial. Any pointer welcome!
As an additional bonus I would also like to filter out specific "null" items like the above dimensions_*.
TiA
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[normalize-space(.) = 0]" />
<xsl:template match="*[normalize-space(.) = '' and count(#*[. = '']) = count(#*)]" />
<!-- write more empty templates for nodes that should be removed -->
</xsl:stylesheet>
Note that count(#*[. = '']) = count(#*) could be written as not(#*[. != '']) if you fancy that.

using Functions vs using templates in XSLT?

What are the pros and cons of functions vs templates in XSLT?
I want to send a unix-timestamp and get an answer like "today" or "tomorrow" or "next week". Which method is most appropriate for this?
The main reason of choosing an <xsl:function> over a named template is the much greater degree of composability of a function.
It is very easy and convenient to write an <xsl:function> that produces the wanted results:
<xsl:function name="my:when" as="xs:string">
<xsl:param name="pDateTime" as="xs:dateTime"/>
<xsl:sequence select=
"for $vToday in xs:dateTime(current-date()),
$vTomorrow in $vToday
+ xs:dayTimeDuration('P1D'),
$vDayAfterTomorrow in $vTomorrow
+ xs:dayTimeDuration('P1D'),
$vNextWeek in $vToday
+ 7* xs:dayTimeDuration('P1D'),
$vNextFortnight in $vNextWeek
+ 7* xs:dayTimeDuration('P1D')
return
if($pDateTime lt $vToday)
then 'in the Past'
else if($pDateTime lt $vTomorrow)
then 'Today'
else if($pDateTime lt $vDayAfterTomorrow)
then 'Tomorrow'
else if($pDateTime lt $vNextWeek)
then 'This week'
else if($pDateTime lt $vNextFortnight)
then 'Next week'
else 'In the Future'
"/>
</xsl:function>
Here is a complete transformation:
<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">
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:sequence select="my:when(current-dateTime())"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P1D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P2D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P3D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P4D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P5D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P6D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P7D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P8D'))"/>,
<xsl:sequence select="my:when(current-dateTime()
+xs:dayTimeDuration('P9D'))"/>
</xsl:template>
<xsl:function name="my:when" as="xs:string">
<xsl:param name="pDateTime" as="xs:dateTime"/>
<xsl:sequence select=
"for $vToday in xs:dateTime(current-date()),
$vTomorrow in $vToday
+ xs:dayTimeDuration('P1D'),
$vDayAfterTomorrow in $vTomorrow
+ xs:dayTimeDuration('P1D'),
$vNextWeek in $vToday
+ 7* xs:dayTimeDuration('P1D'),
$vNextFortnight in $vNextWeek
+ 7* xs:dayTimeDuration('P1D')
return
if($pDateTime lt $vToday)
then 'in the Past'
else if($pDateTime lt $vTomorrow)
then 'Today'
else if($pDateTime lt $vDayAfterTomorrow)
then 'Tomorrow'
else if($pDateTime lt $vNextWeek)
then 'This week'
else if($pDateTime lt $vNextFortnight)
then 'Next week'
else 'In the Future'
"/>
</xsl:function>
</xsl:stylesheet>
when this transformation is applied (to any document -- not used), the wanted, correct result is produced:
Today,
Tomorrow,
This week,
This week,
This week,
This week,
This week,
Next week,
Next week,
Next week
In this case, an external function is best-suited.
XSLT is best suited for pattern matching and transformation, not computation.