Search code examples
xmlloopsxsltapache-fop

Get xml values with xsl using fop from certain positions looping


here is my xsl (part):

<xsl:template name="while">
    <xsl:variable name="VALUE">
        <xsl:value-of select="instData" />
    </xsl:variable>

    <xsl:if test="VALUE=''">
        <xsl:variable name="next_year" select="next_year+1" />
        <xsl:call-template name="while"/>
    </xsl:if>
</xsl:template>

<xsl:template match="/elements">

<xsl:for-each select="values">

<xsl:choose>
    <xsl:when test="(instData != '')">

    <circle cx="{x_coord}" cy="{instData}" r="5" stroke="black" stroke-width="0" fill="{$var_color_instDataCircle}" />

    <xsl:variable name="act_year" select="position()" />
    <xsl:variable name="next_year" select="position()+1" />
    <xsl:variable name="act_x" select="x_coord" />
    <xsl:variable name="act_y" select="instData" />



    <xsl:choose>
        <xsl:when test="next_year/instData = ''">
            <xsl:call-template name="while"/>
        </xsl:when>
    <xsl:otherwise>
        <xsl:variable name="next_x" select="next_year/x_coord" />
        <xsl:variable name="next_y" select="next_year/instData" />
        <line x1="{$act_x}" y1="{$act_y}" x2="{$next_x}" y2="{$next_y}" style="stroke:black;stroke-width:5;" /> 
    </xsl:otherwise>
    </xsl:choose>

    </xsl:when>
    <xsl:otherwise>

    </xsl:otherwise>
</xsl:choose>

</for:each>


</xsl:template>

Here is an xml example

<elements> 
   <values>
    <year>2015</year>
    <x_coord>88</x_coord>
    <instData></instData>
   </values>
   <values>
    <year>2016</year>
    <x_coord>188</x_coord>
    <instData></instData>
   </values>
   <values>
    <year>2017</year>
    <x_coord>288</x_coord>
    <instData>50</instData>
   </values>
    <values>
    <year>2018</year>
    <x_coord>388</x_coord>
    <instData></instData>
   </values>
   <values>
    <year>2019</year>
    <x_coord>488</x_coord>
    <instData></instData>
   </values>
   <values>
    <year>2020</year>
    <x_coord>588</x_coord>
    <instData>100</instData>
   </values>
   <values>
    <year>2021</year>
    <x_coord>688</x_coord>
    <instData>40</instData>
   </values>
   <values>
    <year>2022</year>
    <x_coord>788</x_coord>
    <instData></instData>
   </values>
 </elements>

The point that I try to achieve is to draw a line of the instData values. I get the first point by looping with for-each and than I have the xsl:choose to search for the next value if there is. Get those x_coord and instData values as the second part of the line (x_coord for x2 and instData for y2). If there is only 1 instData than I just draw a point(that part works since I draw all the points in the for-each beforehand). I can't get the values of the next_x and next_y, the x2 part. Any idea on how to get this to work?

Thanks for all your help.


Solution

  • If I understand this correctly, you could do simply:

    <xsl:template match="elements">
        <root>
            <xsl:for-each select="values[string(instData)]">
                <xsl:variable name="next" select="following-sibling::values[string(instData)][1]" />
                <xsl:if test="$next">
                    <line x1="{x_coord}" y1="{instData}" x2="{$next/x_coord}" y2="{$next/instData}" /> 
                </xsl:if>
            </xsl:for-each>
        </root>
    </xsl:template>
    

    to get:

    <root>
      <line x1="288" y1="50" x2="588" y2="100"/>
      <line x1="588" y1="100" x2="688" y2="40"/>
    </root>
    

    P.S. XSLT is a declarative language: xsl:for-each is not a loop, and there is no while because it's not needed.