我有这个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
非常感谢你的帮助。
答案 0 :(得分:2)
首先,如果您使用的是XSLT1.0,则可以使用称为Muenchian Grouping的技术来获取所有程序的不同开始时间。这包括设置一个按键,通过start元素查找程序。
<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 的替代方案。