XSLT 1.0 在多个级别上对多个值进行分组

发布于 2024-10-21 20:49:12 字数 2839 浏览 2 评论 0原文

  • 针对评论进行了编辑 *

您好,

我是一名 XSLT 菜鸟,需要一些帮助。我正在尝试使用 XSLT 1.0 进行过滤器/组组合(不能将 XSLT 2.0 用于此应用程序)。

这是 xml 的示例

<entry>
  <item>
    <name>Widget 2</name>
    <rank>2</rank>
    <types>
       <type>Wood</type>
       <type>Fixed</type>
       <type>Old</type>
    </types>
  </item>
   <item>
    <name>Widget 1</name>
    <rank>2</rank>
    <types>
       <type>Metal</type>
       <type>Broken</type>
       <type>Old</type>
    </types>
  </item>
  <item>
    <name>Widget 3</name>
    <rank>1</rank>
    <types>
       <type>Metal</type>
       <type>New</type>
    </types>
  </item>
</entry>

现在我想做的是输出 html,其中我根据 获取 XML 的子集,然后按排名进行分组。例如,如果用户选择金属类型的所有项目,则输出应为:


排名 1


  • 小部件 3




  • 排名 2


  • 小部件 1



  • 如果用户选择类型 Old,则输出将为


    排名 2


  • 小部件 1

  • 小部件 2



  • 我可以很容易地使用排名键进行分组,但尝试同时执行这两项操作是行不通的。这是我尝试过的 xslt 示例:

    <xsl:param name="typeParam"/>
    <xsl:key name="byRank" use="rank" match="item"/>
    
    <xsl:for-each select="item[count(.|key('byRank',rank)[1])=1]">
      <xsl:sort data-type="number" select="rank"/>
      <xsl:for-each select="key('byRank',rank)">
        <xsl:sort select="name"/>
        <xsl:if test="count(rank)&gt;0">
          <p class="nospace"><font color="#800000"><b>Rank<xsl:value-of select="rank"/></b></font></p>
          <xsl:for-each select="types[types=$typeParam]">
            <li id="mylist"><b><xsl:value-of select="../name"/></b></li>
          </xsl:for-each>
        <br/>
      </xsl:if>
    </xsl:for-each>
    </xsl:for-each>
    

    我从中得到的结果是,我确实获得了我想要的 xml 子集,但它还显示了所有不同的排名值。我想将其限制为 $typeParam 中指定的类型的等级。

    我尝试将 for-each 语句移至代码的前面,并修改 if 语句以选择 $typeParam,但两者都不起作用。我也尝试过将我的密钥与等级和类型连接起来,但这似乎也不起作用(仅当 $typeParam 中的类型是类型下的第一个子级时才有效)。

    谢谢杰夫

    • edited in response to comments *

    Hello,

    I am an XSLT noob and need some help. I am trying to do an filter/group combination with XSLT 1.0 (can't use XSLT 2.0 for this application).

    Here is an example of the xml

    <entry>
      <item>
        <name>Widget 2</name>
        <rank>2</rank>
        <types>
           <type>Wood</type>
           <type>Fixed</type>
           <type>Old</type>
        </types>
      </item>
       <item>
        <name>Widget 1</name>
        <rank>2</rank>
        <types>
           <type>Metal</type>
           <type>Broken</type>
           <type>Old</type>
        </types>
      </item>
      <item>
        <name>Widget 3</name>
        <rank>1</rank>
        <types>
           <type>Metal</type>
           <type>New</type>
        </types>
      </item>
    </entry>
    

    Now what I want to do is output html where I get a subset of the XML based on <type> and then group on rank. For example, if the user selects all items with the type Metal, the output should be:

    <p class="nospace"><font color="#800000">
    <b>Rank 1</b></font></p>
    <li id="mylist"><b>Widget 3</b></li>
    <br\>

    <p class="nospace"><font color="#800000">
    <b>Rank 2</b></font></p>
    <li id="mylist"><b>Widget 1</b></li>
    <br\>

    of if the user user chooses the type Old the output would be

    <p class="nospace"><font color="#800000">
    <b>Rank 2</b></font></p>
    <li id="mylist"><b>Widget 1</b></li>
    <li id="mylist"><b>Widget 2</b></li>
    <br\>

    I can group using keys on rank along easily enough, but trying to do both is not working. Here is a sample of the xslt I have tried:

    <xsl:param name="typeParam"/>
    <xsl:key name="byRank" use="rank" match="item"/>
    
    <xsl:for-each select="item[count(.|key('byRank',rank)[1])=1]">
      <xsl:sort data-type="number" select="rank"/>
      <xsl:for-each select="key('byRank',rank)">
        <xsl:sort select="name"/>
        <xsl:if test="count(rank)>0">
          <p class="nospace"><font color="#800000"><b>Rank<xsl:value-of select="rank"/></b></font></p>
          <xsl:for-each select="types[types=$typeParam]">
            <li id="mylist"><b><xsl:value-of select="../name"/></b></li>
          </xsl:for-each>
        <br/>
      </xsl:if>
    </xsl:for-each>
    </xsl:for-each>
    

    The result I get from this is I do indeed get the subset of my xml that I want but it also displays all of the various rank values. I want to limit it to just the ranks of the type that is specified in $typeParam.

    I have tried moving the for-each statement to earlier in the code as well as modifying the if statement to select for $typeParam but neither works. I have also tried concat-ing my key with rank and type but that doesn't seem to work either (It only works if the type in $typeParam is the first child under types).

    Thanks

    jeff

    如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

    扫码二维码加入Web技术交流群

    发布评论

    需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

    评论(1

    零時差 2024-10-28 20:49:12

    此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:key name="kItemByRank" match="item" use="rank"/>
        <xsl:param name="pType" select="'Old'"/>
        <xsl:template match="entry">
            <xsl:for-each select="item[count(.|key('kItemByRank',rank)[1])=1]">
                <xsl:sort select="rank" data-type="number"/>
                <xsl:variable name="vGroup" select="key('kItemByRank',rank)[
                                                       types/type = $pType
                                                    ]"/>
                <xsl:if test="$vGroup">
                    <p class="nospace">
                        <font color="#800000">
                            <b>
                                <xsl:value-of select="concat('Rank ',rank)"/>
                            </b>
                        </font>
                    </p>
                    <xsl:apply-templates select="$vGroup">
                        <xsl:sort select="name"/>
                    </xsl:apply-templates>
                    <br/>
                </xsl:if>
            </xsl:for-each>
        </xsl:template>
        <xsl:template match="item">
            <li id="mylist">
                <b>
                    <xsl:value-of select="name"/>
                </b>
            </li>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    <p class="nospace">
        <font color="#800000">
            <b>Rank 1</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 3</b>
    </li>
    <br />
    <p class="nospace">
        <font color="#800000">
            <b>Rank 2</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 1</b>
    </li>
    <br />
    

    并将 pType 参数设置为 'Old',输出:

    <p class="nospace">
        <font color="#800000">
            <b>Rank 2</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 1</b>
    </li>
    <li id="mylist">
        <b>Widget 2</b>
    </li>
    <br />
    

    This stylesheet:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:key name="kItemByRank" match="item" use="rank"/>
        <xsl:param name="pType" select="'Old'"/>
        <xsl:template match="entry">
            <xsl:for-each select="item[count(.|key('kItemByRank',rank)[1])=1]">
                <xsl:sort select="rank" data-type="number"/>
                <xsl:variable name="vGroup" select="key('kItemByRank',rank)[
                                                       types/type = $pType
                                                    ]"/>
                <xsl:if test="$vGroup">
                    <p class="nospace">
                        <font color="#800000">
                            <b>
                                <xsl:value-of select="concat('Rank ',rank)"/>
                            </b>
                        </font>
                    </p>
                    <xsl:apply-templates select="$vGroup">
                        <xsl:sort select="name"/>
                    </xsl:apply-templates>
                    <br/>
                </xsl:if>
            </xsl:for-each>
        </xsl:template>
        <xsl:template match="item">
            <li id="mylist">
                <b>
                    <xsl:value-of select="name"/>
                </b>
            </li>
        </xsl:template>
    </xsl:stylesheet>
    

    Output:

    <p class="nospace">
        <font color="#800000">
            <b>Rank 1</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 3</b>
    </li>
    <br />
    <p class="nospace">
        <font color="#800000">
            <b>Rank 2</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 1</b>
    </li>
    <br />
    

    And whit pType param set to 'Old', output:

    <p class="nospace">
        <font color="#800000">
            <b>Rank 2</b>
        </font>
    </p>
    <li id="mylist">
        <b>Widget 1</b>
    </li>
    <li id="mylist">
        <b>Widget 2</b>
    </li>
    <br />
    
    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文