我创建了一个XSLT,用于为鞋类目录分组数据。鞋子需要按“线”和“品牌”分组。行和品牌标题需要出现在每个部分的开头。每条线都有不止一个品牌。每个品牌通常都有不止一双鞋。
以下是一些示例XML数据:
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<shoe>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brand>WALKING</brand>
<style-name>NEW BALANCE-NB 475V2 (WIDE)</style-name>
<color>Black</color>
<price>67.99</price>
</shoe>
<shoe>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brand>WALKING</brand>
<style-name>NEW BALANCE-496 (WIDE)</style-name>
<color>Grey/Pink</color>
<price>64.99</price>
</shoe>
<shoe>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brand>CROSS TRANING</brand>
<style-name>FILA-MEMORY PANACHE</style-name>
<color>Black/Pink</color>
<price>69.99</price>
</shoe>
<shoe>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brand>RUNNING</brand>
<style-name>FILA-VITALITY 2 TRAIL</style-name>
<color>Grey/Prpl/Turq</color>
<price>59.99</price>
</shoe>
<shoe>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brand>CASUAL</brand>
<style-name>LEVI'S-HAMILTON BUCK HI</style-name>
<color>Black/Black</color>
<price>34.99</price>
</shoe>
<shoe>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brand>CASUAL</brand>
<style-name>EVERLAST-EVAN SKATE</style-name>
<color>Black</color>
<price>29.99</price>
</shoe>
<shoe>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brand>RUNNING</brand>
<style-name>SKECHERS-POWER SWITCH (WIDE)</style-name>
<color>Black/White</color>
<price>69.99</price>
</shoe>
<shoe>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brand>RUNNING</brand>
<style-name>SKECHERS-EQUALIZER GEL TOP </style-name>
<color>Black</color>
<price>69.99</price>
</shoe>
</catalog>
这是我的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:key name="shoes-by-line" match="shoe" use="line" />
<xsl:key name="shoes-by-brand" match="shoe" use="concat(line,'#',brand )" />
<xsl:template match="catalog">
<catalog>
<shoes>
<xsl:for-each select="shoe[count(. | key('shoes-by-line', line)[1]) = 1]">
<line>
<xsl:value-of select="line"/>
</line>
<brands>
<brand>
<xsl:value-of select="brand"/>
</brand>
<xsl:for-each select="key( 'shoes-by-brand', concat(line,'#',brand ))">
<shoe>
<style-name>
<xsl:value-of select="style-name"/>
</style-name>
<color>
<xsl:value-of select="color"/>
</color>
<price>
<xsl:value-of select="price"/>
</price>
</shoe>
</xsl:for-each>
</brands>
</xsl:for-each>
</shoes>
</catalog>
</xsl:template>
</xsl:stylesheet>
我得到1“线”和1“品牌”,但我没有在每一行获得额外的品牌。每行应至少有两到三个品牌。在这个XML中有2行。
这是我想要的XML结构:
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lines>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brands>
<brand>WALKING</brand>
<shoes>
<shoe>
<style-name>NEW BALANCE-NB 475V2 (WIDE)</style-name>
<color>Black</color>
<price>67.99</price>
</shoe>
<shoe>
<style-name>NEW BALANCE-496 (WIDE)</style-name>
<color>Grey/Pink</color>
<price>64.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brands>
<brand>CROSS TRANING</brand>
<shoes>
<shoe>
<style-name>FILA-MEMORY PANACHE</style-name>
<color>Black/Pink</color>
<price>69.99</price>
</shoe>
<shoe>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brand>RUNNING</brand>
<style-name>FILA-VITALITY 2 TRAIL</style-name>
<color>Grey/Prpl/Turq</color>
<price>59.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brands>
<brand>CASUAL</brand>
<shoes>
<shoe>
<style-name>LEVI'S-HAMILTON BUCK HI</style-name>
<color>Black/Black</color>
<price>34.99</price>
</shoe>
<shoe>
<style-name>EVERLAST-EVAN SKATE</style-name>
<color>Black</color>
<price>29.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brands>
<brand>RUNNING</brand>
<shoes>
<shoe>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brands>
<brand>RUNNING</brand>
<shoes>
<shoe>
<style-name>SKECHERS-POWER SWITCH (WIDE)</style-name>
<color>Black/White</color>
<price>69.99</price>
</shoe>
<shoe>
<style-name>SKECHERS-EQUALIZER GEL TOP </style-name>
<color>Black</color>
<price>69.99</price>
</shoe>
</shoes>
</brands>
</lines>
</catalog>
答案 0 :(得分:1)
通过对XSLT进行一些调整,可以生成所需的结果:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:key name="shoes-by-line" match="shoe" use="line" />
<xsl:key name="shoes-by-brand" match="shoe" use="concat(line,'#',brand )" />
<xsl:template match="catalog">
<catalog>
<xsl:for-each select="shoe[count(. | key('shoes-by-line', line)[1]) = 1]">
<lines>
<line>
<xsl:value-of select="line"/>
</line>
<brands>
<brand>
<xsl:value-of select="brand"/>
</brand>
<shoes>
<xsl:for-each select="key( 'shoes-by-brand', concat(line,'#',brand ))">
<shoe>
<style-name>
<xsl:value-of select="style-name"/>
</style-name>
<color>
<xsl:value-of select="color"/>
</color>
<price>
<xsl:value-of select="price"/>
</price>
</shoe>
</xsl:for-each>
</shoes>
</brands>
</lines>
</xsl:for-each>
</catalog>
</xsl:template>
</xsl:stylesheet>
您的XSLT已经生成了所需的输出,只需要将一些分组元素移动到不同的位置:
之前:
<catalog>
<shoes>
<xsl:for-each select="shoe[count(. | key('shoes-by-line', line)[1]) = 1]">
<line>
<xsl:value-of select="line"/>
</line>
<brands>
<brand>
<xsl:value-of select="brand"/>
</brand>
<xsl:for-each select="key('shoes-by-brand',
concat(line,'#',brand ))">
<shoe>
...
调整后:
<catalog>
<xsl:for-each select="shoe[count(. | key('shoes-by-line', line)[1]) = 1]">
<lines>
<line>
<xsl:value-of select="line"/>
</line>
<brands>
<brand>
<xsl:value-of select="brand"/>
</brand>
<shoes>
<xsl:for-each select="key('shoes-by-brand',
concat(line,'#',brand ))">
<shoe>
...
更新:正如评论中所注意到的,XSLT上面没有提供正确的输出。就像一个不同的方法:使用xsl:for-each-group
而不是键来跟随XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:template match="catalog">
<catalog>
<xsl:for-each-group select="shoe" group-by="line">
<xsl:for-each-group select="current-group()" group-by="brand">
<lines>
<line>
<xsl:value-of select="line"></xsl:value-of>
</line>
<brands>
<xsl:for-each-group select="current-group()" group-by="brand">
<brand>
<xsl:value-of select="current-grouping-key()"></xsl:value-of>
</brand>
<shoes>
<xsl:for-each select="current-group()">
<shoe>
<style-name>
<xsl:value-of select="style-name"/>
</style-name>
<color>
<xsl:value-of select="color"/>
</color>
<price>
<xsl:value-of select="price"/>
</price>
</shoe>
</xsl:for-each>
</shoes>
</xsl:for-each-group>
</brands>
</lines>
</xsl:for-each-group>
</xsl:for-each-group>
</catalog>
</xsl:template>
</xsl:stylesheet>
当应用于您的输入时,XML会产生以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<lines>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brands>
<brand>WALKING</brand>
<shoes>
<shoe>
<style-name>NEW BALANCE-NB 475V2 (WIDE)</style-name>
<color>Black</color>
<price>67.99</price>
</shoe>
<shoe>
<style-name>NEW BALANCE-496 (WIDE)</style-name>
<color>Grey/Pink</color>
<price>64.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brands>
<brand>CROSS TRANING</brand>
<shoes>
<shoe>
<style-name>FILA-MEMORY PANACHE</style-name>
<color>Black/Pink</color>
<price>69.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 43: WOMENS BRANDED ATHLETIC</line>
<brands>
<brand>RUNNING</brand>
<shoes>
<shoe>
<style-name>FILA-VITALITY 2 TRAIL</style-name>
<color>Grey/Prpl/Turq</color>
<price>59.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brands>
<brand>CASUAL</brand>
<shoes>
<shoe>
<style-name>LEVI'S-HAMILTON BUCK HI</style-name>
<color>Black/Black</color>
<price>34.99</price>
</shoe>
<shoe>
<style-name>EVERLAST-EVAN SKATE</style-name>
<color>Black</color>
<price>29.99</price>
</shoe>
</shoes>
</brands>
</lines>
<lines>
<line>LINE 87: MENS BRANDED ATHLETIC</line>
<brands>
<brand>RUNNING</brand>
<shoes>
<shoe>
<style-name>SKECHERS-POWER SWITCH (WIDE)</style-name>
<color>Black/White</color>
<price>69.99</price>
</shoe>
<shoe>
<style-name>SKECHERS-EQUALIZER GEL TOP </style-name>
<color>Black</color>
<price>69.99</price>
</shoe>
</shoes>
</brands>
</lines>
</catalog>
请注意,与OP中提供的请求输出存在一个差异 - 行RUNNING
的品牌LINE 43: WOMENS BRANDED ATHLETIC
是一个单独的品牌,而不是CROSS TRAINING
品牌,但也许这是想要的输出中的一个小错误。否则,有必要找到一个解决方案,以便在同一品牌中列出RUNNING
和CROSS TRAINING
。
由于应为每一行的每个品牌列出鞋子,<xsl:for-each-group select="shoe" group-by="line">
首先选择按行分组的所有鞋子。然后,使用<xsl:for-each-group select="current-group()" group-by="brand">
按品牌选择此组中的所有品牌,并在循环<xsl:for-each select="current-group()">
中处理品牌的所有鞋子。
更新:正如评论中所提到的,这是一个XSLT 2.0样式表。我刚刚更正了上面模板中的版本。虽然我已经使用在线XSLT测试工具测试了模板,并将其声明为版本1.0,但它没有抛出任何错误(尽管它应该有)。
答案 1 :(得分:0)
我重新访问了XSLT我相信我找到了使用XSLT 1.0的解决方案
<?xml version="1.0" encoding="UTF-8"?><!-- DWXMLSource="D76-shoebook.xml" -->
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8"/>
<xsl:key name="shoes-by-line" match="shoe" use="line"/>
<xsl:key name="shoes-by-brand" match="shoe" use="concat(line, '|', brand)"/>
<xsl:template match="catalog">
<catalog>
<xsl:for-each select="shoe[generate-id() = generate-id(key('shoes-by-line', line)[1])]">
<lines>
<xsl:for-each select="key('shoes-by-line', line)[generate-id() = generate-id(key('shoes-by-brand', concat(line, '|', brand))[1])]">
<line><xsl:value-of select="line"/></line><xsl:text>
</xsl:text><brand><xsl:value-of select="brand"/></brand><xsl:text>
</xsl:text><shoes>
<xsl:for-each select="key('shoes-by-brand', concat(line, '|', brand))">
<shoe>
<style-name><xsl:value-of select="style-name" /></style-name>
<color><xsl:value-of select="color" /></color><xsl:text>
<price><xsl:value-of select="price" /></price><xsl:text>
</xsl:text>
</shoe>
</xsl:for-each>
</shoes>
</xsl:for-each>
</lines>
</xsl:for-each>
</catalog>
</xsl:template>
</xsl:stylesheet>
这会从源XML键入LINE然后在BRAND上生成正确的分组和嵌套。