XSLT beginner: Group XML based on unique element value XSLT 1.0
我是一个初学者,我正在尝试使用 XSLT 1.0 对基于类似类别的 XML 输入进行分组。这是包含类别和位置的输入 xml。输出必须将所有具有相同类别的元素分组并列出唯一位置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?xml version="1.0" ?> <Data> <Row> <id>123</id> <location>/example/games/data.php</location> <category>gamedata</category> </Row> <Row> <id>456</id> <location>/example/games/data.php</location> <category>gamedata</category> </Row> <Row> <id>789</id> <location>/example/games/score.php</location> <category>gamedata</category> </Row> <Row> <id>888</id> <location>/example/games/title.php</location> <category>gametitle</category> </Row> <Row> <id>777</id> <location>/example/games/title.php</location> <category>gametitle</category> </Row> <Row> <id>999</id> <location>/example/score/title.php</location> <category>gametitle</category> </Row> </Data> |
寻找输出(仅列出按类别分组的唯一位置):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <project> <item> <data> <category>gamedata</category> <id>456</id> <id>789</id> <id>123</id> <location>/example/games/data.php</location> <location>/example/games/score.php</location> </data> <data> <category>gametitle</category> <id>888</id> <id>777</id> <id>999</id> <location>/example/games/title.php</location> <location>/example/score/title.php</location> </data> </item></project> |
到目前为止我尝试过的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="keyCategory" match="Row" use="category"/> <xsl:template match="/"> <project xmlns="xyz.com"> <item > <name lang="en">Example</name> <xsl:for-each select="//Row[generate-id(.) = generate-id(key('keyCategory', category)[1])]"> <xsl:for-each select="key('keyCategory', category)"> <data> <category><xsl:value-of select="category"/></category> <id><xsl:value-of select="id"/></id> <location><xsl:value-of select="location"/></location></data> </xsl:for-each> </xsl:for-each> </item> </project> |
我实际上得到了什么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <project> <item> <data> <category>gamedata</category> <id>456</id> <location>/example/games/data.php</location> </data> <data> <category>gamedata</category> <id>789</id> <location>/example/games/score.php</location> </data> <data> <category>gamedata</category> <id>789</id> <location>/example/games/score.php</location> </data> <data> <category>gamedata</category> <id>123</id> <location>/example/games/data.php</location> </data> <data> <category>gametitle</category> <id>888</id> <location>/example/games/title.php</location> </data> <data> <category>gametitle</category> <id>777</id> <location>/example/games/title.php</location> </data> <data> <category>gametitle</category> <id>999</id> <location>/example/score/title.php</location> </data> </item></project> |
对于您的嵌套分组问题,我认为您想使用第二个键:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes"/> <xsl:key name="keyCategory" match="Row" use="category"/> <xsl:key name="location" match="Row" use="concat(category, '|', location)"/> <xsl:template match="/"> <project> <item> <name lang="en">Example</name> <xsl:for-each select="//Row[generate-id(.) = generate-id(key('keyCategory', category)[1])]"> <data> <xsl:copy-of select="category"/> <xsl:copy-of select="key('keyCategory', category)/id"/> <xsl:copy-of select="key('keyCategory', category)[generate-id() = generate-id(key('location', concat(category, '|', location))[1])]/location"/> </data> </xsl:for-each> </item> </project> </xsl:template> </xsl:stylesheet> |
https://xsltfiddle.liberty-development.net/94Acsm4/0
这仅显示分组并忽略您的输出使用不同的命名空间,为了在新命名空间中创建所选元素,我将对其进行转换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://example.com/"> <xsl:output indent="yes"/> <xsl:key name="keyCategory" match="Row" use="category"/> <xsl:key name="location" match="Row" use="concat(category, '|', location)"/> <xsl:template match="/"> <project> <item> <name lang="en">Example</name> <xsl:for-each select="//Row[generate-id(.) = generate-id(key('keyCategory', category)[1])]"> <data> <xsl:apply-templates select="category"/> <xsl:apply-templates select="key('keyCategory', category)/id"/> <xsl:apply-templates select="key('keyCategory', category)[generate-id() = generate-id(key('location', concat(category, '|', location))[1])]/location"/> </data> </xsl:for-each> </item> </project> </xsl:template> <xsl:template match="*"> <xsl:element name="{local-name()}"> <xsl:apply-templates/> </xsl:element> </xsl:template> </xsl:stylesheet> |
https://xsltfiddle.liberty-development.net/94Acsm4/1