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>
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?
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.
This is all about reverse a string. It works properly for the given Value 'ABCDEF'. The output is also correct 'FEDCBA'. But I want to know how this is printing letters 'A' and 'D' in this string. Could anyone help me to understand this? please.
Elaborate this working method.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output method="html"/>
<xsl:template name="reverse">
<xsl:param name="input" select="'ABCDEF'"/>
<xsl:variable name="len" select="string-length($input)"/>
<xsl:choose>
<xsl:when test="$len < 2">
<xsl:value-of select="$input"/>
</xsl:when>
<xsl:when test="$len = 2">
<xsl:value-of select="substring($input,2,1)"/>
<xsl:value-of select="substring($input,1,1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="mid" select="floor($len div 2)"/>
<xsl:call-template name="reverse">
<xsl:with-param name="input" select="substring($input,$mid+1,$mid+1)"/>
</xsl:call-template>
<xsl:call-template name="reverse">
<xsl:with-param name="input" select="substring($input,1,$mid)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<xsl:call-template name="reverse">
</xsl:call-template>
</xsl:template>
</xsl:stylesheet>
Here's what happens:
Input ABCDEF
len = 6
len is > 2 and not = 2
mid = 3
Call again with input DEF
len = 3
len is > 2 and not = 2
mid = 1
Call again with input EF
len = 2
len is not > 2 but = 2
Put out the second letter F
Put out the first letter E
Return to outer call
Call with input = D
len is less than 2
Output D
Return to outer call
Call again with input = ABC
len = 3
len is > 2 and not 2
mid = 1
Call again with input BC
len = 2
len is not > 2 but = 2
Put out the second letter C
Put out the first letter B
Return to outer call
Call with input A
len is less than 2
Output A
I am trying to increment a counter when a condition is met, for example if a final_score is over 30, count = 1. so if 3 scores are over 30 the final_score should be 3. To get the scores i need to add previous scores so the final score is the calculation of all the other scores
for example
Example XML
<scores>
<score result="20" />
<score result="10" />
<score redult="5" />
</score>
Main XSL
<xsl:call-template name="scores">
<xsl:with-param name="prev_count" select="0"/>
</xsl:call-template>
Template for scores
<template name="scores">
<param name="counter" select="0">
<xsl:variable name="prev_counter" select="$counter+1" />
<xsl:for-each select="persons/person[id=#id]">//get all the scores
<xsl:varable name="total_score" select="sum(scores/score)" />//sum them all up
<xsl:if test="total_score > 40" > //check the result
<xsl:value-of select="$counter">
<xsl:call-template name="scores">
<xsl:with-param name="counter" select="$counter+1"/>
</xsl:call-template>
</xsl:if>
<xsl:for-each>
</xsl:template>
</xsl:template>
I just cannot work it out, or is my approach way off?
If I have understood correctly, to count the number of person elements, where the total of the score elements is greater than 30, just use this expression (assuming you are currently positioned on the parent persons element)
<xsl:value-of select="count(person[sum(scores/score/#result) > 30])" />