我在xml中有数据,该数据提供了产品及其价格的列表。寻找XSLT可以帮助我得出每种产品的最高价格。尝试可能还没有运气。请帮忙。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Product>
<name>P1</name>
<price>10</price>
</Product>
<Product>
<name>P1</name>
<price>20</price>
</Product>
<Product>
<name>P2</name>
<price>5</price>
</Product>
<Product>
<name>P3</name>
<price>8</price>
</Product>
<Product>
<name>P1</name>
<price>30</price>
</Product>
</root>
预期输出
Product Price
P1 30
P2 5
P3 8
答案 0 :(得分:0)
Using XSLT 2.0 it is quite easy:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each-group select="Product" group-by="name">
<xsl:value-of select="concat(current-grouping-key(),
' ', max(current-group()/price), '
')"/>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
As you can see, there is needed a for-each-group
loop,
selecting Product
elements and grouping them on the value
of child name
element.
Inside the loop, current-grouping-key()
function provides the key of the current group
(value of name
element) and max(current-group()/price)
computes the
maximal price.
For a working example see http://xsltransform.net/pNEhB3c
Your task can be accomplished also in XSLT 1.0, using so called Muenchian Grouping (for more detailed description search the Web).
The first thing to do is to create a key, grouping elements to be grouped (Product) under some grouping key (in our case name):
<xsl:key name="prods" match="Product" use="name"/>
Then the actual grouping can be performed in a for-each
loop,
using a predicate with a Muenchian Grouping idiom inside:
[generate-id()=generate-id(key('prods', name)[1])]
An additional point of difficulty is that XSLT 1.0 has so much
limited capabilities, that it even does not have max
function.
To circumvent this limitation, we have to write a template (I called it maximum), which takes a sequence of elements, sorts them (descending) and outputs the first (maximum) value.
This template is called for price
children elements of all
Product
elements from the current group.
So the whole script can look like below:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:key name="prods" match="Product" use="name"/>
<xsl:template match="root">
<xsl:text>Product Price
</xsl:text>
<xsl:for-each select="Product[generate-id()=
generate-id(key('prods', name)[1])]">
<xsl:value-of select="concat(name, ' ')"/>
<xsl:call-template name="maximum">
<xsl:with-param name="src" select="key('prods', name)/price"/>
</xsl:call-template>
<xsl:value-of select="'
'"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="maximum">
<xsl:param name="src"/>
<xsl:for-each select="$src">
<xsl:sort select="." data-type="number" order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:transform>
For a working example see http://xsltransform.net/pNEhB3c/1