Xml 使用XSLT对数据进行分组并不完全有效

Xml 使用XSLT对数据进行分组并不完全有效,xml,xslt,Xml,Xslt,我创建了一个XSLT,用于对鞋子目录的数据进行分组。鞋子需要按“线”和“品牌”进行分组。行和品牌名称需要出现在每个部分的开头。每条生产线都有多个品牌。每个品牌通常都有不止一只鞋 以下是一些示例XML数据: <?xml version="1.0" encoding="UTF-8"?> <catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <shoe> <line>LIN

我创建了一个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>

第43行:女性品牌运动鞋
行走
新天平-NB 475V2(宽)
黑色
67.99
第43行:女性品牌运动鞋
行走
新余额-496(宽)
灰色/粉红色
64.99
第43行:女性品牌运动鞋
交叉训练
FILA-MEMORY华丽
黑色/粉红色
69.99
第43行:女性品牌运动鞋
跑步
菲拉2号小径
灰色/Prpl/Turq
59.99
第87行:男士品牌运动鞋
随便的
李维斯汉密尔顿巴克你好
黑色/黑色
34.99
第87行:男士品牌运动鞋
随便的
EVERLAST-EVAN滑板
黑色
29.99
第87行:男士品牌运动鞋
跑步
SKECHERS-电源开关(宽)
黑/白
69.99
第87行:男士品牌运动鞋
跑步
SKECHERS-EQUALIZER凝胶顶部
黑色
69.99
这是我的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>

我得到了一个“线”和一个“品牌”,但我没有在每一行得到额外的品牌。每条生产线至少应有两到三个品牌。在这个XML中有两行

以下是我想要的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>

第43行:女性品牌运动鞋
行走
新天平-NB 475V2(宽)
黑色
67.99
新余额-496(宽)
灰色/粉红色
64.99
第43行:女性品牌运动鞋
交叉训练
FILA-MEMORY华丽
黑色/粉红色
69.99
第43行:女性品牌运动鞋
跑步
菲拉2号小径
灰色/Prpl/Turq
59.99
第87行:男士品牌运动鞋
随便的
李维斯汉密尔顿巴克你好
黑色/黑色
34.99
EVERLAST-EVAN滑板
黑色
29.99
第87行:男士品牌运动鞋
跑步
第87行:男士品牌运动鞋
跑步
SKECHERS-电源开关(宽)
黑/白
69.99
SKECHERS-EQUALIZER凝胶顶部
黑色
69.99

对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>
应用于输入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>

第43行:女性品牌运动鞋
行走
新天平-NB 475V2(宽)
黑色
67.99
新余额-496(宽)
灰色/粉红色
64.99
第43行:女性品牌运动鞋
交叉训练
FILA-MEMORY华丽
黑色/粉红色
69.99
第43行:女性品牌运动鞋
跑步
菲拉2号小径
灰色/Prpl/Turq
59.99
第87行:男士品牌运动鞋
随便的
李维斯汉密尔顿巴克你好
黑色/黑色
34.99
EVERLAST-EVAN滑板
黑色
29.99
第87行:男士品牌运动鞋
跑步
SKECHERS-电源开关(宽)
黑/白
69.99
SKECHERS-EQUALIZER凝胶顶部
黑色
69.99
请注意,与OP中给出的请求输出有一个不同之处-第43行的品牌
RUNNING
:女子品牌田径是一个单独的品牌,而不是
交叉训练
品牌,但这可能是所需输出中的一个小错误。否则,必须找到解决方案,使
运行
交叉培训
列在同一品牌中

由于应为每条生产线的每个品牌列出鞋款,
首先选择按生产线分组的所有鞋款。然后,使用
按品牌选择该组中的所有品牌,并在循环中处理该品牌的所有鞋子


更新:如评论中所述,这是一个XSLT 2.0样式表。我刚刚更正了上面模板中的版本。虽然我已经使用在线XSLT测试工具测试了该模板,并将其声明为1.0版,但它没有抛出任何错误(尽管它应该有)

我重温了XSLT,我相信我找到了使用XSLT1.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键控生成适当的分组和嵌套

在我看来,如果您添加了对所做调整的解释,您的答案可能会有很大的改进。@MathiasMüller感谢您的关注,我现在添加此内容是因为我同意您的观点,也不喜欢只提供代码答案(尽管此处的调整很小)
<?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 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>
<?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>