XSLT 初学者:Group XML 基于唯一元素值 XSLT 1.0
XSLT beginner: Group XML based on unique element value XSLT 1.0
我是初学者,我正在尝试使用 XSLT 1.0 根据相似类别对 XML 输入进行分组。这是包含类别和位置的输入 xml。输出必须将所有具有相同类别的元素分组并列出唯一位置:
<?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>
寻找输出为(仅列出按类别分组的唯一位置):
<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>
到目前为止我尝试过的:
<?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>
我实际得到的是:
<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>
对于你的嵌套分组问题,我认为你想使用第二个键:
<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
这仅显示分组并忽略您的输出使用不同的命名空间,要在新命名空间中创建选定元素,我将转换它们:
<?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>
我是初学者,我正在尝试使用 XSLT 1.0 根据相似类别对 XML 输入进行分组。这是包含类别和位置的输入 xml。输出必须将所有具有相同类别的元素分组并列出唯一位置:
<?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>
寻找输出为(仅列出按类别分组的唯一位置):
<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>
到目前为止我尝试过的:
<?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>
我实际得到的是:
<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>
对于你的嵌套分组问题,我认为你想使用第二个键:
<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
这仅显示分组并忽略您的输出使用不同的命名空间,要在新命名空间中创建选定元素,我将转换它们:
<?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>