Xsl with an if statement + add something to a variable
Clash Royale CLAN TAG#URR8PPP
Xsl with an if statement + add something to a variable
I am trying to show an output where the total_p_calib
is a value of an for cycle where I have an if statement that compares my values to see if sum(clb:quantidade) < ../../clb:quantidade
is equal and if it's not I would like to put the difference between both in a variable and show it in the end of the for cycle.
total_p_calib
sum(clb:quantidade) < ../../clb:quantidade
XML file
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="style_macaMoimenta.xsl"?>
<moimenta xmlns="http://www.macamoimenta.pt/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gnr="http://www.macamoimenta.pt/general" xmlns:clt="http://www.macamoimenta.pt/lote"
xmlns:prc="http://www.macamoimenta.pt/precario"
xmlns:clb="http://www.macamoimenta.pt/calibragem"
xsi:schemaLocation="http://www.macamoimenta.pt/ moimenta.xsd">
<produtores>
<produtor>
<codigo>PR001</codigo>
<nome>Antonio Manuel</nome>
<data_registo>2018-03-20</data_registo>
<morada>
<gnr:rua>Rua Antonio Manuel</gnr:rua>
<gnr:numero>69</gnr:numero>
<gnr:cod_postal>4569-123</gnr:cod_postal>
</morada>
<colheita>
<ano>2018</ano>
<qualidade>Ambrosia</qualidade>
<cod_colheita>FE23569</cod_colheita>
<valor>
<prc:precario>
<prc:valor>0-60</prc:valor>
<prc:preco>0.10</prc:preco>
</prc:precario>
<prc:precario>
<prc:valor>60-65</prc:valor>
<prc:preco>0.13</prc:preco>
</prc:precario>
<prc:precario>
<prc:valor>65-70</prc:valor>
<prc:preco>0.17</prc:preco>
</prc:precario>
<prc:precario>
<prc:valor>DEFEITO</prc:valor>
<prc:preco>0.05</prc:preco>
</prc:precario>
</valor>
<lotes>
<lote>
<clt:n_lote>236598</clt:n_lote>
<clt:quantidade>2500</clt:quantidade>
<clt:calibragem>
<clb:calib>
<clb:valor>0-60</clb:valor>
<clb:quantidade>1000</clb:quantidade>
</clb:calib>
<clb:calib>
<clb:valor>60-65</clb:valor>
<clb:quantidade>0</clb:quantidade>
</clb:calib>
<clb:calib>
<clb:valor>65-70</clb:valor>
<clb:quantidade>1300</clb:quantidade>
</clb:calib>
<clb:calib>
<clb:valor>DEFEITO</clb:valor>
<clb:quantidade>200</clb:quantidade>
</clb:calib>
</clt:calibragem>
</lote>
</lotes>
</colheita>
</produtor>
</produtores>
</moimenta>
XSL file
<?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:m="http://www.macamoimenta.pt/"
xmlns:gnr="http://www.macamoimenta.pt/general"
xmlns:clt="http://www.macamoimenta.pt/lote"
xmlns:prc="http://www.macamoimenta.pt/precario"
xmlns:clb="http://www.macamoimenta.pt/calibragem"
exclude-result-prefixes="xs" version="1.0"
xmlns:datetime="http://exslt.org/dates-and-times">
<xsl:template match="/">
<html>
<body >
<div border="1">
<img src="Maça_moimenta.png" id="over" height="100"/>
</div>
<xsl:for-each select="m:moimenta/m:produtores">
<xsl:for-each select="m:produtor/m:colheita/m:lotes/m:lote/clt:calibragem/clb:calib">
<xsl:if test="sum(clb:quantidade) < ../../clb:quantidade">
<!-- Here i don't knot what to put --->
</xsl:if>
</xsl:for-each>
<div> Value: <!-- the total value on the variable --> </div>
</body>
</html>
</xsl:template>
I need to do it for every produtor
that is why I have two for cycles!
produtor
It's a comparation between the sum of the values inside of the moimenta/produtores/produtor/colheita/calibragem/calib/quantidade
and moimenta/produtores/produtor/colheita/calibragem/quantidade
(this is the bigger one)
moimenta/produtores/produtor/colheita/calibragem/calib/quantidade
moimenta/produtores/produtor/colheita/calibragem/quantidade
2 Answers
2
The language of your first paragraph is very procedural ("I want to put ... compare ... see ... put ... show"). That's not a good way to approach functional programming, because it's a reverse engineering job to unravel that.
Your final paragraph is the kind of language you should be using to describe requirements "It's a comparison between the sum of X and the sum of Y". Unfortunately it's not quite precise enough as a requirements statement. And you don't show your desired output.
So our only way of working out what you want to achieve is by trying to guess what you intended with your incomplete and non-working code.
The only thing we can say for certain is that the approach you are following won't work. You can't change the value of a variable within a loop (in fact, there are no loops, only mapping functions).
You seem to be using XSLT 1.0, which actually makes this kind of calculation quite difficult. The sum()
function in XSLT 1.0 only works on sets of nodes, not on sets of computed numbers, which is what you need here. If you can move to XSLT 2.0 (or 3.0) then it will make your life easier.
sum()
The typical way to sum computed values in XSLT 1.0 is with recursion: you need to write a named template that is called to process one value, which then calls itself to process the next value, passing the "result so far" as a parameter, and returning the final result when you get to the last thing in the input.
Recursion in functional programming is the equivalent of looping in procedural languages. Having powerful operators for working on sets of values mean you often don't need explicit recursion, but the functions and operators in 1.0 often aren't powerful enough.
You don't need any xsl:for-each
loops.
xsl:for-each
Just calculate the sum()
of all m:colheita/m:lotes/m:lote/clt:calibragem/clb:calib/clb:quantidade
and the sum()
of all m:colheita/m:lotes/m:lote/clt:quantidade
and then subtract one from the other to find the $difference
.
sum()
m:colheita/m:lotes/m:lote/clt:calibragem/clb:calib/clb:quantidade
sum()
m:colheita/m:lotes/m:lote/clt:quantidade
$difference
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:m="http://www.macamoimenta.pt/"
xmlns:gnr="http://www.macamoimenta.pt/general"
xmlns:clt="http://www.macamoimenta.pt/lote"
xmlns:prc="http://www.macamoimenta.pt/precario"
xmlns:clb="http://www.macamoimenta.pt/calibragem"
exclude-result-prefixes="xs" version="1.0"
xmlns:datetime="http://exslt.org/dates-and-times">
<xsl:template match="/">
<html>
<body>
<div border="1">
<img src="Maça_moimenta.png" id="over" height="100"/>
</div>
<xsl:variable name="total" select="sum(m:moimenta/m:produtores/m:produtor/m:colheita/m:lotes/m:lote/clt:calibragem/clb:calib/clb:quantidade)"/>
<xsl:variable name="difference" select="sum(m:moimenta/m:produtores/m:produtor/m:colheita/m:lotes/m:lote/clt:quantidade) - $total "/>
<xsl:if test="$difference != 0">
<div> Difference: <xsl:value-of select="$difference"/> </div>
</xsl:if>
<div> Value: <xsl:value-of select="$total"/> </div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
is it possible to do a variable without select something or select null and after put something inside it?
– Miguel Sousa
10 hours ago
No, you are approaching the problem procedurally. You need to think declaratively.
– Mads Hansen
10 hours ago
You might need a separate for-each, or apply-templates in a different mode. It would be easier to help demonstrate how if you described the desired output. You are likely having difficulty because not approaching it in a declarative XSLT manner.
– Mads Hansen
9 hours ago
What i need to do is to do the comparation between those values and if they are not equal i need to add the difference to a variable and in the end show the total of the difference
– Miguel Sousa
9 hours ago
If you want the total difference, for each section, just get the sums in one shot and calculate the difference. I've updated the solution.
– Mads Hansen
22 secs ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
i can not move to the 2.0 version because i need to show it in a browser. Sorry for the english
– Miguel Sousa
9 hours ago