xslt arborescence works only partially - xslt

I use xslt to extract information form a xml file.
the xml file is :
<object>
<identifier>identifier</identifier>
<link>UD</link>
<title>Current Title</tite>
<impact>
<product>The product</product>
<evolution id="Evo 1">
<descr>Current description</descr>
</evolution>
</impact>
</object>
my xlst file is :
<xsl:for-each select="//object">
<tr>
<td>
<xsl:value-of select="identifier"/>
</td>
<td>
<xsl:value-of select="link"/>
</td>
<td>
<xsl:value-of select="title"/>
</td>
<td>
<xsl:value-of select="impact[1]/product"/>
</td>
<td>
<xsl:value-of select="impact[1]/product/evolution[1]/#id"/>
</td>
<td>
<xsl:value-of select="impact[1]/product/evolution[1]/descr"/>
</td>
</tr>
However, I can't seem to get the last two xsl values, I must have made a mistake (the first 4 columns are OK). Could you explain me why ?

Evolution is a sibling, not a child of product - it is a direct child of impact.
<xsl:value-of select="impact[1]/evolution[1]/#id"/>
<xsl:value-of select="impact[1]/evolution[1]/descr"/>

Related

sxl: How to check if a row has particular column value?

I have a code that return each row, but how can i filter them based on one of the returned column values?
<xsl:for-each select="//Sqls/Stuff/Row">
<tr>
<td>
<xsl:value-of select="First" />
</td>
<td>
<xsl:value-of select="Second" />
</td>
<td>
<xsl:value-of select="Third" />
</td>
<td>
<xsl:value-of select="Fourth" />
</td>
</tr>
</xsl:for-each>
So how can i make this code return only rows where "Third" equals to "SHOWTHIS"?
Thanks.
Try:
<xsl:for-each select="//Sqls/Stuff/Row[Third='SHOWTHIS']">
You could wrap the tr in an xsl:if block and test the value of //Sqls/Stuff/Row/Third
https://msdn.microsoft.com/en-us/library/ms256209.aspx

nested xsl:for-each does not work

I woud like to make some nested loops over my xml doc
Here is my xml
<evolutionlist>
<date id="22_05_2014">
<objet>
<identifier>1VD5-3452-8R5</identifier>
<link>Link1</link>
<title>EXCHANGE OF ELEMENTS</title>
</objet>
<objet>
<identifier>1V24-34A2-8C5</identifier>
<link>Link1</link>
<title>NEW ELEMENT</title>
</objet>
</date>
<date id="21_05_2014">
<identifier>1VV4-34A2-8C5</identifier>
<link>Link2</link>
<title>REPLACE</title>
</date>
</evolutionlist>
Ideally, I woudl like to display something like
22_05_2014
objet1 (with add infos)
objet2 (with add infos)
21_05_2014
objet3 (with add infos)
I made:
<xsl:for-each select="//date">
<xsl:value-of select="#id"/>
<xsl:for-each select="objet">
<tr>
<td>
<xsl:value-of select="identifier"/>
</td>
<td>
<xsl:value-of select="link"/>
</td>
<td>
<xsl:value-of select="title"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
but I got
22_05_2014 21_05_2014
objet1
objet2
objet3
where did I go wrong ?
EDIT
I tried
<xsl:for-each select="./objet">
for the second loop but that did not work either
Shame on me !
I forgot to do this:
<tr>
<td>
<xsl:value-of select="./#id"/>
</td>
</tr>
You were right, Ian Roberts, by encouraging me do write the real code

XSL Sum of nodes

I am trying to calculate the SUM of some nodes. A Learner will have 1 or more Learning Aims, and I need to know the total of the GLH node for the Learning Aims for the learner.
Here is some sample XML.
<Learner>
<LearnRefNumber>422</LearnRefNumber>
<FamilyName>John</FamilyName>
<GivenNames>Smith</GivenNames>
<LearningDelivery>
<LearnAimRef>zilsk14a</LearnAimRef>
<AimType>4</AimType>
<AimSeqNumber>1</AimSeqNumber>
<GLH>2775</GLH>
</LearningDelivery>
<LearningDelivery>
<LearnAimRef>zilsk14b</LearnAimRef>
<AimType>4</AimType>
<AimSeqNumber>2</AimSeqNumber>
<GLH>2500</GLH>
</LearningDelivery>
</Learner>
Here is my XSL. The count of the Learning Aims works fine, but I am struggling to SUM up the GLH.
<xsl:for-each select="t:Learner">
<div class="learner">
<xsl:variable name="LearningAims" select="count(t:LearningDelivery)" />
<xsl:variable name="LearnerGLH" select="sum(t:LearningDelivery/GLH)" />
<table>
<tr>
<th>Learner Ref</th>
<th>Learning Aims</th>
<th>Total GLH</th>
</tr>
<tr>
<td>
<xsl:value-of select="t:LearnRefNumber" />
</td>
<td>
<xsl:value-of select="$LearningAims" />
</td>
<td>
<xsl:value-of select="$LearnerGLH" />
</td>
</tr>
</table>
</div>
Please help. Many thanks
You're writing sum(t:LearningDelivery/GLH), but in the input XML the LearningDelivery and GLH elements are in the same namespace. You want sum(t:LearningDelivery/t:GLH).

Remove values after point

I want to Remove the zeros or any other values after point(eg 12.000000000000).
I am using xslt code .my code is like
<xsl:if test="value!= ''">
<tr>
<td>
value
</td>
<td>
<xsl:value-of select="value"/>
</td>
</tr>
</xsl:if>
how can I achive this?
Use Number formatting as:
<xsl:if test="value!= ''">
<tr>
<td>
value
</td>
<td>
<xsl:value-of select="format-number(value,'0')"/>
</td>
</tr>
</xsl:if>
You can use the format-number function:
<xsl:value-of select="format-number(value,'#')"/>
Refer to:
http://www.w3.org/TR/xslt/#format-number
Just use:
substring-before(concat(value, '.'), '.')
This works for any value -- not just a number. The result is correct even if value doesn't contain any dot character.

XML to table, how to get position() of context node to the specified ancestor(s)

I have such xml:
<A1>
<B1>
<C1>
<C2>
<C3>
</B1>
<B2>
<C4>
<C5>
<C6>
</B2>
</A1>
<A2>
<B3>
<C7>
<C8>
<C9>
</B3>
<B4>
<C10>
<C11>
<C12>
</B4>
</A2>
I need to transform it to table with nested rows:
<table border="yes">
<tr>
<td>A1</td>
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<td></td>
<td></td>
<td>C2</td>
</tr>
<tr>
<td></td>
<td></td>
<td>C3</td>
</tr>
<tr>
<td></td>
<td>B2</td>
<td>C3</td>
</tr>
<tr>
<td></td>
<td></td>
<td>C4</td>
</tr>
A and B appear only if they are new (not repeating in every row);
I'm trying to use position()
<xsl:template match="c">
<tr>
<td>
<xsl:if test="IT IS THE FIRST C IN A">
<xsl:value-of select="ancestor::A"/>
</xsl:if>
</td>
<td>
<xsl:if test="position(1)">
<xsl:value-of select="parent"/>
</xsl:if>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
It seems that we should emulate position() for ancestor.
Is there a general solution for any number of nested rows?
You perhaps need something like the following (if I understood your question correctly):
<xsl:template match="C">
<tr>
<td>
<xsl:if test="generate-id(ancestor::A/descendant::C[1]) = generate-id(.)">
<xsl:value-of select="ancestor::A"/>
</xsl:if>
</td>
<td>
<xsl:if test="not(previous-sibling::C)">
<xsl:value-of select=".."/>
</xsl:if>
</td>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="descendant::C"/>
</xsl:template>
Edit: you may also use
not(previous-sibling::C) and not(../previous-sibling::B)
as the first test (instead of using generate-id()).