XSLT: выберите один idref и найдите corr. элемент
У меня есть XML-файл о фильмах, который выглядит следующим образом (короткая версия)
<movie id="movie_tt0004994">
<title>Bound on the Wheel </title>
<stars idref="star_nm0933368 star_nm0913085 star_nm0151606"/>
</movie>
<star id="star_nm0933368">
<name>Elsie Jane Wilson</name>
</star>
Я хочу преобразовать этот xml в html, используя xslt. HTML должен быть таблицей с названием фильма в первом столбце и звездочкой NAMES (не более 3) в следующих трех столбцах.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<html>
<body>
<h2>movie list</h2>
<table border="1">
<th>Title</th>
<th colspan="3">Stars</th>
</tr>
<xsl:for-each select="IMDb/movie">
<tr>
<td><xsl:value-of select="title" /></td>
<xsl:for-each select="stars/@idref">
<xsl:variable name="curr_ref" select="."/>
<td><xsl:value-of select="//IMDb/star[@id=$curr_ref]/name"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</font>
</body>
</html>
</xsl:template>
</xsl:transform>
Проблема в том, что он работает только для фильмов с одной звездой. Если в звездах есть несколько звездных идентификаторов (как в фильме в данной части моего xml), то соответствующие столбцы в моей таблице остаются пустыми. Я думаю, это потому, что строка делает curr_ref одной длинной строкой из всех idref вместо трех отдельных. Как я должен идти об этом?
1 ответ
Предполагая, что XSLT 2.0 вы можете использовать
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="star" match="star" use="@id"/>
<xsl:template match="/">
<html>
<body>
<h2>movie list</h2>
<table border="1">
<tr>
<th>Title</th>
<th colspan="3">Stars</th>
</tr>
<xsl:for-each select="IMDb/movie">
<tr>
<td><xsl:value-of select="title" /></td>
<xsl:for-each select="for $ref in tokenize(stars/@idref, '\s+') return key('star', $ref)">
<td><xsl:value-of select="name"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:transform>
Предполагая поддержку XSLT 1.0 (или более поздней) и DTD, вы можете использовать
<!DOCTYPE IDMb [
<!ATTLIST star
id ID #REQUIRED>
<!ATTLIST stars
idref IDREFS #REQUIRED>
]>
<IMDb>
<movie id="movie_tt0004994">
<title>Bound on the Wheel </title>
<stars idref="star_nm0933368 star_nm0913085 star_nm0151606"/>
</movie>
<star id="star_nm0933368">
<name>Elsie Jane Wilson</name>
</star>
</IMDb>
а также
<xsl:template match="/">
<html>
<body>
<h2>movie list</h2>
<table border="1">
<tr>
<th>Title</th>
<th colspan="3">Stars</th>
</tr>
<xsl:for-each select="IMDb/movie">
<tr>
<td><xsl:value-of select="title" /></td>
<xsl:for-each select="id(stars/@idref)">
<td><xsl:value-of select="name"/></td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>