0

I am using XSLT 1.0 I transform the following xml file:

<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet type="text/xsl" href="test_1.xsl"?> <Features> <Feature item="a1" area="1"></Feature> <Feature item="a1" area="1"></Feature> <Feature item="a2" area="1"></Feature> <Feature item="a2" area="1"></Feature> <Feature item="b1" area="1"></Feature> <Feature item="b1" area="1"></Feature> <Feature item="b2" area="1"></Feature> </Features> 

via this xsl file:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:key name="KeyStyle" match="Feature" use="@style"/> <xsl:key name="KeyItem" match="Feature" use="@item"/> <xsl:template match="Features"> <html> <xsl:for-each select="Feature[generate-id() = generate-id(key('KeyStyle',@style)[1])]"> <xsl:sort select="@style" order="ascending"/> Table for style (<xsl:value-of select="@style"/>) <xsl:for-each select="key('KeyStyle',@style)"> <xsl:sort select="@item" order="ascending"/> <xsl:if test="not(preceding::*[@item = current()/@item])"> <p>Style=<xsl:value-of select="@style"/></p> <p>Item=<xsl:value-of select="@item"/></p> <p>TotalAreaOf_Items (<xsl:value-of select="@item"/>)=<xsl:value-of select="sum(key('KeyItem',@item)/@area)"/></p> </xsl:if> </xsl:for-each> ---------- <br/><br/> </xsl:for-each> </html> </xsl:template> </xsl:stylesheet> 

Getting this output:

<html> Table for style (a) <p>Item=a1</p> <p>TotalAreaOf_Items (a1)=4</p> <p>Item=a2</p> <p>TotalAreaOf_Items (a2)=4</p> ----------------- Table for style (b) <p>Item=b1</p> <p>TotalAreaOf_Items (b1)=3</p> <p>Item=b2</p> <p>TotalAreaOf_Items (b2)=3</p> </html> 

Since substring(@item, 1, 1) statement scans all (a) items ignoring what follows after (a), I apparently get the sum of all items starting with (a) : TotalAreaOf_Items (a1)=4 and TotalAreaOf_Items (a2)=4

instead of the desired : TotalAreaOf_Items (a1)=2 and TotalAreaOf_Items (a2)=2

I try to handle the <xsl:value-of select="sum(key('KeyItem'... with a separate key, but the two prevailing nested xsl:for-each statements have already assigned which way the scanning is performed. Any help will be valuable.

2
  • 1
    Instead of @style use substring(@item, 1, 1), in both the xsl:key definition and the calls to the key() function. Commented Jun 23, 2024 at 12:53
  • 2
    P.S. I see you have asked 13 questions, but did not accept a single answer. Please read: stackoverflow.com/help/someone-answers. Commented Jun 23, 2024 at 12:56

1 Answer 1

0

I had to add an extra key:

<xsl:key name="KeyItem1" match="Feature" use="@item"/> 

and get sum through:

<p>TotalAreaOf_Items (<xsl:value-of select="@item"/>)=<xsl:value-of select="sum(key('KeyItem1',@item)/@area)"/></p> 

The final xsl file:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:key name="KeyItem" match="Feature" use="substring(@item, 1, 1)"/> <xsl:key name="KeyItem1" match="Feature" use="@item"/> <xsl:template match="Features"> <html> <xsl:for-each select="Feature[generate-id() = generate-id(key('KeyItem',substring(@item, 1, 1))[1])]"> <xsl:sort select="@item" order="ascending"/> Table for style (<xsl:value-of select="substring(@item, 1, 1)"/>) <xsl:for-each select="key('KeyItem',substring(@item, 1, 1))"> <xsl:sort select="@item" order="ascending"/> <xsl:if test="not(preceding::*[@item = current()/@item])"> <p>Item=<xsl:value-of select="@item"/></p> <p>TotalAreaOf_Items (<xsl:value-of select="@item"/>)=<xsl:value-of select="sum(key('KeyItem1',@item)/@area)"/></p> </xsl:if> </xsl:for-each> ----------------- <br/><br/> </xsl:for-each> </html> </xsl:template> </xsl:stylesheet> 

The desired output (sums of @area of all nodes with the same @item)

<html> Table for style (a) <p>Item=a1</p> <p>TotalAreaOf_Items (a1)=2</p> <p>Item=a2</p> <p>TotalAreaOf_Items (a2)=2</p> ----------------- Table for style (b) <p>Item=b1</p> <p>TotalAreaOf_Items (b1)=2</p> <p>Item=b2</p> <p>TotalAreaOf_Items (b2)=1</p> </html> 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.