XSLT组按列表中的属性条目

时间:2011-06-20 12:58:36

标签: php xslt

我在使用正确的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来检查每个国家/地区的项目(国家/地区是模板),因此这是在国家/地区模板中。

如果我现在为每个项目,我得到所有项目。但我想首先列出一个独特的公司名称,因此将项目分组在那里。

我可以做两次转换吗?首先将项目分组为重复的公司节点,然后在第二次转换中将它们分成一个字段?

4 个答案:

答案 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>