Reputation: 1763
file_1.xml
<productlist>
<items>
<item>Pen</item>
<price>8</item>
</items>
<items>
<item>Pen</item>
<price>5</item>
</items>
<items>
<item>Pen</item>
<price>10</item>
</items>
<items>
<item>Bag</item>
<price>15</item>
</items>
<items>
<item>Bag</item>
<price>22</item>
</items>
<items>
<item>Bag</item>
<price>20</item>
</items>
</productlist>
file_2.xml
<productlist>
<items>
<item>Pen</item>
</items>
<items>
<item>Bag</item>
</items>
</productlist>
need out put like below with max and min value using xsl 1.0
<productlist>
<items>
<item>Pen</item>
<min>5</min>
<max>10</max>
</items>
<items>
<item>Bag</item>
<min>15</min>
<max>22</max>
</items>
</productlist>
Upvotes: 4
Views: 16037
Reputation: 1873
10 years too late... but I found this question had a high rank in SO and the following might be an easier answer to follow if someone's still looking for a solution in XSL 1.0
Instead of the above "pure" XSL answer, you might simply be able to use the math:min function if it's available in your XSL 1.0 processor.
This works for me with Xalan 2.7.2 and Java 11 (openjdk version "11.0.1" 2018-10-16).
<xsl:variable name="minprice" select="math:min(productlist/items/price)"/>
You might need to specify the namespace xmlns:math="http://exslt.org/math (but it wasn't necessary for me) I realized after answering this question that I was using XSL 1.1 which doesn't require the namespace to be declared. With XSL 1.0 you will need to declare it: xmlns:math="http://exslt.org/math
(Thanks to @michael.hor257k)
among others, math:max also exists as a function, obviously to get the maximum value of an item in XSL 1.0.
By the way, the example XML in the question itself is incorrectly formed.
/price should close price, not /item
as in
<price>8</item>
should be
<price>8</price>
Upvotes: 0
Reputation: 221
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="productlist"/>
</xsl:template>
<xsl:template match="productlist">
<productlist>
<xsl:variable name="intermediate">
<xsl:for-each-group select="items" group-by="item">
<items>
<item>
<xsl:value-of select="item"/>
</item>
<prices>
<xsl:for-each select="current-group()">
<price>
<xsl:value-of select="price"/>
</price>
</xsl:for-each>
</prices>
</items>
</xsl:for-each-group>
</xsl:variable>
<xsl:for-each select="$intermediate/items">
<items>
<item>
<xsl:value-of select="item"/>
</item>
<xsl:for-each select="prices">
<min>
<xsl:value-of select="min(price)"/>
</min>
<max>
<xsl:value-of select="max(price)"/>
</max>
</xsl:for-each>
</items>
</xsl:for-each>
</productlist>
</xsl:template>
</xsl:stylesheet>
Upvotes: -1
Reputation: 167716
Sort and then takes the first for the minimum and the last item for the maximum:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="data-url" select="'file_1.xml'"/>
<xsl:variable name="data-doc" select="document($data-url)"/>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key name="k1" match="items" use="item"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="items">
<xsl:variable name="this" select="."/>
<xsl:copy>
<xsl:copy-of select="item"/>
<xsl:for-each select="$data-doc">
<xsl:for-each select="key('k1', $this/item)">
<xsl:sort select="price" data-type="number" order="ascending"/>
<xsl:if test="position() = 1">
<min>
<xsl:value-of select="price"/>
</min>
</xsl:if>
<xsl:if test="position() = last()">
<max>
<xsl:value-of select="price"/>
</max>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When I apply above stylesheet with Saxon 6.5.5 on the input document
<productlist>
<items>
<item>Pen</item>
</items>
<items>
<item>Bag</item>
</items>
</productlist>
where the other file is
<productlist>
<items>
<item>Pen</item>
<price>8</price>
</items>
<items>
<item>Pen</item>
<price>5</price>
</items>
<items>
<item>Pen</item>
<price>10</price>
</items>
<items>
<item>Bag</item>
<price>15</price>
</items>
<items>
<item>Bag</item>
<price>22</price>
</items>
<items>
<item>Bag</item>
<price>20</price>
</items>
</productlist>
I get the wanted result
<productlist>
<items>
<item>Pen</item>
<min>5</min>
<max>10</max>
</items>
<items>
<item>Bag</item>
<min>15</min>
<max>22</max>
</items>
</productlist>
Upvotes: 8