-1

我有这个 XML 文件,我需要通过 xsl/t 将其转换为表格。

<?xml version="1.0" encoding="ISO-8859-1"?>

<TVGuide start="2001-07-05" end="2001-07-05">
  <Channel>
    <Name>BBC1</Name>
    <Program>
      <Start>2001-07-05T19:00:00</Start>
      <Duration>PT30M</Duration>
      <Series>A QuestionOfSport</Series>
      <Title></Title>
    </Program>
    <Program rating="5" flag="favorite">
      <Start>2001-07-05T19:30:00</Start>
      <Duration>PT30M</Duration>
      <Series>EastEnders</Series>
      <Title></Title>
      <Description>
        Mark's health scare forces him to reconsider his future with Lisa,
        while Jamie is torn between Sonia and Zoe.
      </Description>
      <CastList>
        <CastMember>
          <Character><Name>Zoe Slater</Name></Character>
          <Actor><Name>Michelle Ryan</Name></Actor>
        </CastMember>
        <CastMember>
          <Character><Name>Jamie Mitchell</Name></Character>
          <Actor><Name>Jack Ryder</Name></Actor>
        </CastMember>
        <CastMember>
          <Character><Name>Sonia Jackson</Name></Character>
          <Actor><Name>Natalie Cassidy</Name></Actor>
        </CastMember>
      </CastList>
      <Writers>
        <Writer><Name>Nick Saltrese</Name></Writer>
        <Writer><Name>Julie Wassmer</Name></Writer>
      </Writers>
      <Director><Name>Stewart Edwards</Name></Director>
      <Producer><Name>Emma Turner</Name></Producer>
    </Program>
    <Program type="documentary">
      <Start>2001-07-05T20:00:00</Start>
      <Duration>PT45M</Duration>
      <Series></Series>
      <Title>Get Real with Casualty</Title>
    </Program>
    <Program>
      <Start>2001-07-05T20:45:00</Start>
      <Duration>PT45M</Duration>
      <Series>Lottery</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T21:30:00</Start>
      <Duration>PT1H</Duration>
      <Series>Panorama</Series>
      <Title></Title>
    </Program>
  </Channel>
  <Channel>
    <Name>BBC2</Name>
    <Program>
      <Start>2001-07-05T19:00:00</Start>
      <Duration>PT1H</Duration>
      <Series>Snooker</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T20:00:00</Start>
      <Duration>PT1H</Duration>
      <Series>HomeFront</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T21:00:00</Start>
      <Duration>PT50M</Duration>
      <Series>WildAfrica</Series>
      <Title></Title>
    </Program>
    <Program flag="interesting">
      <Start>2001-07-05T21:50:00</Start>
      <Duration>PT40M</Duration>
      <Series>Taboo</Series>
      <Title>Nakedness</Title>
    </Program>
  </Channel>
  <Channel>
    <Name>ITV</Name>
    <Program>
      <Start>2001-07-05T19:00:00</Start>
      <Duration>PT30M</Duration>
      <Series>Emmerdale</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T19:30:00</Start>
      <Duration>PT30M</Duration>
      <Series>CoronationStreet</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T20:00:00</Start>
      <Duration>PT1H</Duration>
      <Series>Millionaire</Series>
      <Title></Title>
    </Program>
    <Program type="drama">
      <Start>2001-07-05T21:00:00</Start>
      <Duration>PT2H</Duration>
      <Series></Series>
      <Title>Hot Money</Title>
    </Program>
  </Channel>
  <Channel>
    <Name>Channel 4</Name>
    <Program>
      <Start>2001-07-05T19:00:00</Start>
      <Duration>PT55M</Duration>
      <Series>Channel4News</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T19:55:00</Start>
      <Duration>PT5M</Duration>
      <Series>SlotArt</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T20:00:00</Start>
      <Duration>PT30M</Duration>
      <Series>Brookside</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T20:30:00</Start>
      <Duration>PT30M</Duration>
      <Series>Brookside</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T21:00:00</Start>
      <Duration>PT1H</Duration>
      <Series>Swallow</Series>
      <Title></Title>
    </Program>
    <Program flag="favorite">
      <Start>2001-07-05T22:00:00</Start>
      <Duration>PT1H</Duration>
      <Series>AllyMcBeal</Series>
      <Title></Title>
    </Program>
  </Channel>
  <Channel>
    <Name>Channel 5</Name>
    <Program>
      <Start>2001-07-05T19:00:00</Start>
      <Duration>PT30M</Duration>
      <Series>MovieChartShow</Series>
      <Title></Title>
    </Program>
    <Program>
      <Start>2001-07-05T19:30:00</Start>
      <Duration>PT30M</Duration>
      <Series>FiveNews</Series>
      <Title></Title>
    </Program>
    <Program type="entertainment">
      <Start>2001-07-05T20:00:00</Start>
      <Duration>PT1H</Duration>
      <Series></Series>
      <Title>The World's Worst Drivers Caught On Tape</Title>
    </Program>
    <Program type="film">
      <Start>2001-07-05T21:00:00</Start>
      <Duration>PT1H55M</Duration>
      <Series></Series>
      <Title>Black and White</Title>
    </Program>
  </Channel>
</TVGuide>

我知道问题可能出在 xsl 文件中。我不是专家,我会非常感谢您的帮助。

这是 xsl 文件。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:key name="hatchala" match="/TVGuide/Channel/Program" use="Start"/>
  <xsl:template match="/">

        <table border="1">

            <tr>hours
              <xsl:call-template name="tvchan"/>
            </tr>
            <tr>
              <th>
              <xsl:call-template name="hour"/>
              </th>
            </tr>

        </table> 
  </xsl:template>
  <xsl:template name="tvchan">
    <xsl:for-each select="/TVGuide/Channel">

      <th>
        <td>
          <xsl:value-of select ="Name"/>
        </td>

      </th>
    </xsl:for-each>

  </xsl:template>
  <xsl:template name="hour">
          <xsl:for-each  select="/TVGuide/Channel/Program[not(./Start=following::Start)]">
            <xsl:sort select="Start"/>
            <xsl:variable name="zman" select ="Start"/>
            <tr>
              <td>
                <xsl:value-of select="Start"/>
              </td>

              <xsl:for-each  select="/TVGuide/Channel/Program[Start=$zman]">
                <xsl:variable name="name1">
                  <xsl:choose>
                    <xsl:when test="Title!=''">
                      <xsl:value-of select="Title"/>
                    </xsl:when>
                    <xsl:otherwise>
                      <xsl:value-of select="Series"/>
                    </xsl:otherwise>

                  </xsl:choose>
                </xsl:variable>
                <td>
                  <xsl:value-of select="$name1"/>

                </td>
          </xsl:for-each>
            </tr>
          </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

结果应该显示一个包含所有程序和时间的表格。

http://dl.dropbox.com/u/99771726/table.png

非常感谢你的帮助。

4

1 回答 1

2

首先,如果您使用的是 XSLT1.0,您可以使用一种称为 Muenchian Grouping 的技术来获取所有程序的不同开始时间。这包括设置一个键来通过它们的开始元素查找程序。

<xsl:key name="hatchala" match="Program" use="Start"/>

请注意,您不一定需要Program元素的完整 Xpath,因为键将在任何级别查找它们(如果您在不同级别有此类元素并想要限制它们,您只会量化事物)。

然后,为了获得不同的开始时间,您将查找恰好是该元素在键中第一次出现的程序的开始时间

<xsl:apply-templates 
   select="/TVGuide/Channel/Program
      [generate-id() = generate-id(key('hatchala', Start)[1])]" mode="header">

('mode' 的使用很快就会清楚,因为最终的 XSLT 将多次匹配Program元素)。

我还将定义一个键来在给定的开始时间查找给定频道的节目

<xsl:key name="hatchala2" match="Program" use="concat(../Name, '|', Start)"/>

然后,对于给定的开始时间,您将遍历所有频道,就像这样......

<xsl:apply-templates select="/TVGuide/Channel" mode="program">
    <xsl:with-param name="Start" select="Start"/>
</xsl:apply-templates>

然后模板匹配这个,可以使用键查找程序

<xsl:template match="Channel" mode="program">
   <xsl:param name="Start"/>
   <td>
      <xsl:apply-templates select="key('hatchala2', concat(Name, '|', $Start))" mode="program"/>
   </td>
</xsl:template>

这是完整的 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>
   <xsl:key name="hatchala" match="Program" use="Start"/>
   <xsl:key name="hatchala2" match="Program" use="concat(../Name, '|', Start)"/>

   <xsl:template match="/TVGuide">
      <table border="1">
         <tr>
            <th>hours</th>
            <xsl:apply-templates select="Channel" mode="header"/>
         </tr>
         <tr>
            <th>
               <xsl:apply-templates select="/TVGuide/Channel/Program[generate-id() = generate-id(key('hatchala', Start)[1])]" mode="header">
                  <xsl:sort select="Start"/>
               </xsl:apply-templates>
            </th>
         </tr>
      </table>
   </xsl:template>

   <xsl:template match="Channel" mode="header">
      <th>
         <xsl:value-of select="Name"/>
      </th>
   </xsl:template>

   <xsl:template match="Program" mode="header">
      <tr>
         <td>
            <xsl:value-of select="Start"/>
         </td>
         <xsl:apply-templates select="/TVGuide/Channel" mode="program">
            <xsl:with-param name="Start" select="Start"/>
         </xsl:apply-templates>
      </tr>
   </xsl:template>

   <xsl:template match="Channel" mode="program">
      <xsl:param name="Start"/>
      <td>
         <xsl:apply-templates select="key('hatchala2', concat(Name, '|', $Start))" mode="program"/>
      </td>
   </xsl:template>

   <xsl:template match="Program" mode="program">
      <xsl:choose>
         <xsl:when test="Title!=''">
            <xsl:value-of select="Title"/>
         </xsl:when>
         <xsl:otherwise>
            <xsl:value-of select="Series"/>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
</xsl:stylesheet>

然后输出如下

<table border="1">
   <tr>
      <th>hours</th>
      <th>BBC1</th>
      <th>BBC2</th>
      <th>ITV</th>
      <th>Channel 4</th>
      <th>Channel 5</th>
   </tr>
   <tr>
      <th>
         <tr>
            <td>2001-07-05T19:00:00</td>
            <td>A QuestionOfSport</td>
            <td>Snooker</td>
            <td>Emmerdale</td>
            <td>Channel4News</td>
            <td>MovieChartShow</td>
         </tr>
         <tr>
            <td>2001-07-05T19:30:00</td>
            <td>EastEnders</td>
            <td/>
            <td>CoronationStreet</td>
            <td/>
            <td>FiveNews</td>
         </tr>
         <tr>
            <td>2001-07-05T19:55:00</td>
            <td/>
            <td/>
            <td/>
            <td>SlotArt</td>
            <td/>
         </tr>
         <tr>
            <td>2001-07-05T20:00:00</td>
            <td>Get Real with Casualty</td>
            <td>HomeFront</td>
            <td>Millionaire</td>
            <td>Brookside</td>
            <td>The World's Worst Drivers Caught On Tape</td>
         </tr>
         <tr>
            <td>2001-07-05T20:30:00</td>
            <td/>
            <td/>
            <td/>
            <td>Brookside</td>
            <td/>
         </tr>
         <tr>
            <td>2001-07-05T20:45:00</td>
            <td>Lottery</td>
            <td/>
            <td/>
            <td/>
            <td/>
         </tr>
         <tr>
            <td>2001-07-05T21:00:00</td>
            <td/>
            <td>WildAfrica</td>
            <td>Hot Money</td>
            <td>Swallow</td>
            <td>Black and White</td>
         </tr>
         <tr>
            <td>2001-07-05T21:30:00</td>
            <td>Panorama</td>
            <td/>
            <td/>
            <td/>
            <td/>
         </tr>
         <tr>
            <td>2001-07-05T21:50:00</td>
            <td/>
            <td>Nakedness</td>
            <td/>
            <td/>
            <td/>
         </tr>
         <tr>
            <td>2001-07-05T22:00:00</td>
            <td/>
            <td/>
            <td/>
            <td>AllyMcBeal</td>
            <td/>
         </tr>
      </th>
   </tr>
</table>

请注意使用xsl:apply-templates而不是xsl:for-each以避免过多的嵌套代码,并尝试使其更易于阅读。

如果您想要一个主要使用xsl:for-each的版本,请尝试使用此 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>
   <xsl:key name="hatchala" match="Program" use="Start"/>
   <xsl:key name="hatchala2" match="Program" use="concat(../Name, '|', Start)"/>

   <xsl:template match="/TVGuide">
      <table border="1">
         <tr>
            <th>hours</th>
            <xsl:for-each select="Channel">
               <th>
                  <xsl:value-of select="Name"/>
               </th>
            </xsl:for-each>
         </tr>
         <tr>
            <th>
               <xsl:for-each select="/TVGuide/Channel/Program[generate-id() = generate-id(key('hatchala', Start)[1])]">
                  <xsl:sort select="Start"/>

                  <xsl:variable name="Start" select="Start" />
                  <tr>
                     <td>
                        <xsl:value-of select="$Start"/>
                     </td>
                     <xsl:for-each select="/TVGuide/Channel">
                        <td>
                           <xsl:apply-templates select="key('hatchala2', concat(Name, '|', $Start))" />
                        </td>
                     </xsl:for-each>
                  </tr>                  
               </xsl:for-each>
            </th>
         </tr>
      </table>
   </xsl:template>

   <xsl:template match="Program">
      <xsl:value-of select="Series"/>
   </xsl:template>

   <xsl:template match="Program[Title!='']">
      <xsl:value-of select="Title"/>
   </xsl:template>
</xsl:stylesheet>

这应该产生相同的输出。请注意,我留下了一个xsl:apply-templates ,因为它产生了模式匹配的好处,并提供了xsl:choose的替代方案。

于 2012-09-11T13:05:27.433 回答