【问题标题】:XSLT: select one idref and find corr. elementXSLT:选择一个 idref 并找到 corr。元素
【发布时间】:2017-04-09 23:05:44
【问题描述】:

我有一个关于电影的 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>

我想使用 xslt 将此 xml 转换为 html。 html应该是一个表格,第一列是电影标题,后面三列是星号(最多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>

问题是它只适用于只有一颗星的电影。如果星星中有多个星星 id(就像我的 xml 给定部分的电影中一样),那么我表中的相应列保持为空。我认为这是因为该行然后使 curr_ref 成为所有 idref 的一个长字符串,而不是三个单独的字符串。我该怎么办?

【问题讨论】:

  • 您是否受限于 XSLT 1.0?或者您可以将 XSLT 2.0 与例如&lt;xsl:key name="star" match="star" use="@id"/&gt; 和例如&lt;xsl:for-each select="for $ref in tokenize(starts/@idref, '\s+') return key('star', $ref)"&gt;&lt;td&gt;...&lt;/td&gt;&lt;/xsl:for-each&gt;?
  • 当然,首选的解决方案是更改您的 XML 架构,因为要存储许多项目,应该使用 节点 的集合(而不是用字符存储它们级分隔符)。
  • @LittleSanti,模式语言有一个w3.org/TR/xmlschema-2/#IDREFS 类型,它是一个空格分隔的 IDREF 值序列,因此假设一个模式表示很好。只有模式感知 XSLT 2.0 不像一般 XSLT 2.0 那样广泛支持,例如 Saxon 9 只有 EE 支持模式感知 XSLT 2.0 或 3.0。
  • @MartinHonnen 好的。很高兴知道。谢谢。

标签: xml xslt 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-26
    • 2021-09-21
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多