我在使用正确的XSLT创建一组基于属性值的元素时遇到问题。这是我的XML:
<companies>
<country iso="DE">
<item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
<item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
<item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
</country>
<country iso="SE">
<item name="Sweet Mixed Pickles" company="Snack Inc." />
<item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
<item name="Leisure Luv Apples" company="Snack Inc." />
</country>
</companies>
我想扩展国家/地区列表,并在包含该公司项目的公司内插入一次公司条目。
我已经运行了基本的XSLT设置,并且国家/地区列表正常运行。我开始使用for-each来检查每个国家/地区的项目(国家/地区是模板),因此这是在国家/地区模板中。
如果我现在为每个项目,我得到所有项目。但我想首先列出一个独特的公司名称,因此将项目分组在那里。
我可以做两次转换吗?首先将项目分组为重复的公司节点,然后在第二次转换中将它们分成一个字段?
答案 0 :(得分:3)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kItemByCompCountry" match="item"
use="concat(../@iso,'+++',@company)"/>
<xsl:template match="*[not(self::item)]">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"item[generate-id()
=
generate-id(key('kItemByCompCountry',
concat(../@iso,
'+++',@company)
)[1]
)
]
">
<company name="{@company}">
<xsl:copy-of select=
"key('kItemByCompCountry',
concat(../@iso,'+++',@company))"/>
</company>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<companies>
<country iso="DE">
<item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
<item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
<item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
</country>
<country iso="SE">
<item name="Sweet Mixed Pickles" company="Snack Inc." />
<item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
<item name="Leisure Luv Apples" company="Snack Inc." />
</country>
</companies>
生成想要的正确结果:
<companies>
<country iso="DE">
<company name="Snack Inc.">
<item name="Strawberry Raw Pressed Juice" company="Snack Inc." />
<item name="Sweet Apple Raw Pressed Juice" company="Snack Inc." />
</company>
<company name="Max Food Ltd.">
<item name="Apple Raw Pressed Juice" company="Max Food Ltd." />
</company>
</country>
<country iso="SE">
<company name="Snack Inc.">
<item name="Sweet Mixed Pickles" company="Snack Inc." />
<item name="Leisure Luv Apples" company="Snack Inc." />
</company>
<company name="Baked Beans A/S">
<item name="Apple Raw Pressed Juice" company="Baked Beans A/S" />
</company>
</country>
</companies>
答案 1 :(得分:1)
喜欢这个?:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="company" match="item" use="@company" />
<xsl:template match="companies">
<xsl:copy>
<xsl:for-each select="country/item[generate-id() = generate-id(key('company',@company)[1])]">
<xsl:variable name="company" select="@company" />
<company name="{$company}">
<xsl:apply-templates select="../../country/item[@company = $company]" />
</company>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<item name="{@name}" country="{../@iso}" />
</xsl:template>
</xsl:stylesheet>
这使用Muenchian分组方法按公司分组。如果您需要了解更多信息,可以使用谷歌。
答案 2 :(得分:1)
<xsl:key name="groupCompanies" match="item" use="@company" />
<xsl:template match="companies">
<xsl:for-each select="//item[generate-id() = generate-id( key('groupCompanies', @company)) [1] ) ]">
<xsl:sort select="@company" order="ascending" />
<xsl:call-template name="group">
<xsl:with-param name="ck" select="@company" />
</xsl:call-template>
</xsl:for-each>
</xsl:template>
<xsl:template name="group">
<xsl:param name="ck" />
<xsl:for-each select="//item[@company = $ck]">
....
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 3 :(得分:1)
根本不要“for-each”,你不需要它。您可以直接从country
元素进行分组:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="country">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="item[
preceding-sibling::item/@company!=@company]"
mode="group"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item" mode="group">
<company name="{@company}">
<xsl:apply-templates select="../item[
@company=current()/@company]"/>
</company>
</xsl:template>
<xsl:template match="item">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
此转换产生:
<companies>
<country iso="DE">
<company name="Max Food Ltd.">
<item name="Apple Raw Pressed Juice" company="Max Food Ltd."/>
</company>
<company name="Snack Inc.">
<item name="Strawberry Raw Pressed Juice" company="Snack Inc."/>
<item name="Sweet Apple Raw Pressed Juice" company="Snack Inc."/>
</company>
</country>
<country iso="SE">
<company name="Baked Beans A/S">
<item name="Apple Raw Pressed Juice" company="Baked Beans A/S"/>
</company>
<company name="Snack Inc.">
<item name="Sweet Mixed Pickles" company="Snack Inc."/>
<item name="Leisure Luv Apples" company="Snack Inc."/>
</company>
</country>
</companies>