按类别和子类别分组,以便从XML数据生成HTML列表

时间:2013-07-24 19:11:13

标签: xml xslt xls muenchian-grouping

我有一些看起来像这样的xml数据:

<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="course-catalog.xsl"?>

<catalog>
    <course>
        <category>Category 1</category>
        <subcategory>Sub 1</subcategory>
        <name>test name 1</name>
        <instructor>fred derp</instructor>
        <date>July 1</date>
        <url>http://foo.com</url>
    </course>

<course>
    <category>Category 1</category>
    <subcategory>Sub 2</subcategory>
    <name>test name 2</name>
    <instructor>john bravo</instructor>
    <date>March 19, 2008</date>
    <url>www.foorl.com/foo.html</url>
</course>

<course>
    <category>Category 2</category>
    <subcategory>Sub 1</subcategory>
    <name>test name 3</name>
    <instructor>Jack Nicholson</instructor>
    <date>July 2</date>
    <url>test.html</url>
</course>

<course>
    <category>Category 2</category>
    <subcategory>Sub 1</subcategory>
    <name>test name 4</name>
    <instructor>Jim Carrey</instructor>
    <date>July 21</date>
    <url>test3.html</url>
</course>




</catalog>

我希望它按类别和子类别进行分组(仅对类别和子类别使用H1 H2标签,并在其下方使用其余的课程数据)。

使用我提供的xml数据,它应该产生:

Category 1
  Sub 1
   test name 1, fred derp, July 1

  Sub 2
   test name 2, john bravo, March 19, 2008

Category 2
  Sub 1
....
...

因此它应该有一个使用xsl的组和一个子组。它不必是在表格或任何东西,只是一个常规的HTML列表。

我尝试过使用此网站上的示例,但找不到任何适用于我需要做的事情。我也尝试过W3学校,它只是展示了一个使用CD的例子,根本没有分组。

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

标记了这个“Muenchian-grouping”后,我假设你需要一个XSLT 1.0的解决方案。在XSLT 2.0中,分组解决方案总是更容易。

对于XSLT 1.0中的多级分组,我更喜欢使用基于变量的分组方法而不是Muenchian基于密钥的分组方法,承认执行速度较慢但更容易理解编码。

t:\ftemp>type armando.xml 
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="course-catalog.xsl"?>

<catalog>
    <course>
        <category>Category 1</category>
        <subcategory>Sub 1</subcategory>
        <name>test name 1</name>
        <instructor>fred derp</instructor>
        <date>July 1</date>
        <url>http://foo.com</url>
    </course>

<course>
    <category>Category 1</category>
    <subcategory>Sub 2</subcategory>
    <name>test name 2</name>
    <instructor>john bravo</instructor>
    <date>March 19, 2008</date>
    <url>www.foorl.com/foo.html</url>
</course>

<course>
    <category>Category 2</category>
    <subcategory>Sub 1</subcategory>
    <name>test name 3</name>
    <instructor>Jack Nicholson</instructor>
    <date>July 2</date>
    <url>test.html</url>
</course>

<course>
    <category>Category 2</category>
    <subcategory>Sub 1</subcategory>
    <name>test name 4</name>
    <instructor>Jim Carrey</instructor>
    <date>July 21</date>
    <url>test3.html</url>
</course>

</catalog>
t:\ftemp>call xslta armando.xml armando.txt 
Producing armando.txt...

t:\ftemp>type armando.txt 

Category 1
  Sub 1
   test name 1, fred derp, July 1
  Sub 2
   test name 2, john bravo, March 19, 2008

Category 2
  Sub 1
   test name 3, Jack Nicholson, July 2
   test name 4, Jim Carrey, July 21

t:\ftemp>type course-catalog.xsl 
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

<xsl:output method="text"/>

<xsl:template match="catalog">
  <xsl:variable name="categories" select="course"/>
  <xsl:for-each select="$categories">
    <xsl:if test="generate-id(.)=
                  generate-id($categories[category=current()/category][1])">
      <xsl:variable name="subs"
                    select="$categories[category=current()/category]"/>
      <xsl:text>&#xa;</xsl:text>
      <xsl:value-of select="category"/>
      <xsl:for-each select="$subs">
        <xsl:if test="generate-id(.)=
                      generate-id($subs[subcategory=current()/subcategory][1])">
          <xsl:text>&#xa;  </xsl:text>
          <xsl:value-of select="subcategory"/>
          <xsl:for-each select="$subs[subcategory=current()/subcategory]">
            <xsl:text>&#xa;   </xsl:text>
            <xsl:value-of select="concat(name,', ',instructor,', ',date)"/>
          </xsl:for-each>
        </xsl:if>
      </xsl:for-each>
      <xsl:text>&#xa;</xsl:text>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
t:\ftemp>rem Done!