如何使用XSLT循环遍历xml文档中的元素

时间:2014-08-21 09:19:10

标签: xml xslt altova

我正在使用XSLT循环遍历XML文档。
文档的根节点称为电影,它可以包含一个或多个电影元素。但是,这些电影元素包含除 actor 元素之外的单个元素。如何循环显示多个演员?我已经使用<xsl:for-each>循环播放每部电影 这是xslt:

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

<xsl:template match="/movies">

<html>
    <head>
    <link rel="stylesheet" href="stylecss.css" />
        <title>My Movies Collection</title>
    </head>
    <body>
        <!-- Use for each loop to extract all child nodes and their information-->

    <xsl:for-each select="/movies/movie">
    <!--Add title as well as year-->
        <h1><xsl:value-of select="title" />
        <xsl:text> ( </xsl:text>
        <xsl:value-of select="@year" />
        <xsl:text> ) </xsl:text>

        </h1>
        <p>
        <img>
            <xsl:attribute name="src">
            <xsl:value-of select="poster" />
            </xsl:attribute>
        </img>
        <span id="details">

        <xsl:text>Review: </xsl:text>
        <xsl:value-of select="@review" />
        <xsl:text>, Type: </xsl:text>
        <xsl:value-of select="@type" />
        <br></br>

        <xsl:text>Producer: </xsl:text>
        <xsl:value-of select="producer" /> 
        <br/>

        <xsl:text>Actor: </xsl:text>
        <xsl:value-of select="actor"/> <br/>

        <xsl:text>Director: </xsl:text>
        <xsl:value-of select="director" /><br/>
        <br/>


<i>         <xsl:text>Comments: </xsl:text>
        <xsl:value-of select="comments" /> </i>



        </span>
        </p>

    </xsl:for-each>

    </body>

</html>



</xsl:template>
</xsl:stylesheet>



xml文档本身:

<?xml version="1.0" encoding="UTF-8"?>

<?xml-stylesheet type="text/xsl" href="stylesheet.xslt" ?>
<movies>
  <movie type="comedy" rating="PG" review="4" year="1997">
  <title>How To Be A Player</title>
  <writer>Mark Brown</writer>
  <producer>Todd R. Baker</producer>
  <director>Russell Simmons</director>
  <actor>Bill Bellamy</actor>
  <actor>Mari Morrow</actor>
  <poster>img/htbap.jpeg</poster>
  <comments>Promotes polygamy</comments>  
  </movie>


  <movie type="comedy" rating="PG" review="5" year="2010">
  <title>Grown Ups</title>
  <writer>Adam Sandler</writer>
  <producer>Jack Giarraputo</producer>
  <director>Fred Wolf</director>
  <actor>Chris Rock</actor>
  <actor>Rob Schneider</actor>
  <poster>img/gu.jpeg</poster>
  <comments>Funny stuff</comments>  
  </movie>

 <movie type="drama" rating="PG" review="5" year="2010">
  <title>The Social Network</title>
  <writer>Dana Brunetti</writer>
  <producer>Scott Rudin</producer>
  <director>David Fincher</director>
  <actor>Jesse Eisenberg</actor>
  <actor>Justin Timberlake</actor>
  <poster>img/sn.jpeg</poster>
  <comments>So innovative</comments>  
  </movie>

  <movie type="comedy" rating="PG" review="5" year="2012">
        <title>Project X</title>
        <writer>Nima Nourizadeh</writer>
        <producer>Todd Phillips</producer>
        <director>Nima Nourizadeh</director>
        <actor>Thomas Mann</actor>
        <actor>Oliver Cooper</actor>
        <poster>img/px.jpeg</poster>
        <comments>Best party to ever</comments>
    </movie> 

</movies>

2 个答案:

答案 0 :(得分:3)

@Tim C:非常好的答案,+1为此!但是 actor 节点的额外template也可以完成这项工作,对吗?

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

    <xsl:template match="/movies">
        <html>
            <head>
                <link rel="stylesheet" href="stylecss.css"/>
                <title>My Movies Collection</title>
            </head>
            <body>
                <!-- Use for each loop to extract all child nodes and their information-->

                <xsl:for-each select="/movies/movie">
                    <!--Add title as well as year-->
                    <h1>
                        <xsl:value-of select="title"/>
                        <xsl:text> ( </xsl:text>
                        <xsl:value-of select="@year"/>
                        <xsl:text> ) </xsl:text>
                    </h1>

                    <p>
                        <img>
                            <xsl:attribute name="src">
                                <xsl:value-of select="poster"/>
                            </xsl:attribute>
                        </img>
                        <span id="details">
                            <xsl:text>Review: </xsl:text>
                            <xsl:value-of select="@review"/>
                            <xsl:text>, Type: </xsl:text>
                            <xsl:value-of select="@type"/>
                            <br></br>
                            <xsl:text>Producer: </xsl:text>
                            <xsl:value-of select="producer"/>
                            <br/>
                            <xsl:text>Actor: </xsl:text>
                            <!-- <xsl:value-of select="actor"/> -->

                            <!-- apply the 'actor' node -->
                            <xsl:apply-templates select="actor"/>

                            <br/>
                            <xsl:text>Director: </xsl:text>
                            <xsl:value-of select="director"/>
                            <br/>
                            <br/>
                            <i>
                                <xsl:text>Comments: </xsl:text>
                                <xsl:value-of select="comments"/>
                            </i>
                        </span>
                    </p>
                </xsl:for-each>

            </body>
        </html>
    </xsl:template>

    <!-- the additional actor template -->
    <xsl:template match="actor">
        <!-- get the value -->
        <xsl:value-of select="."/>
        <!-- set a comma and a whitespace if it is not the last 'actor' node -->
        <xsl:if test="position() != last()">
            <xsl:text>, </xsl:text>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

答案 1 :(得分:2)

没有理由可以将xsl:for-each嵌套在另一个中。所以你可以用这个

替换<xsl:value-of select="actor"/>,它只输出第一个演员的文本
 <xsl:for-each select="actor">
     <xsl:value-of select="." /><br />
 </xsl:for-each>

请注意select中的xpath表达式是相对表达式;它与您当前所在的movie节点相关,因此将选择作为其子元素的所有actor元素。 (这也意味着您当前的<xsl:for-each select="/movies/movie">实际上只能是<xsl:for-each select="movie">

话虽如此,在XSLT中,通常最好使用基于模板的解决方案,而不是使用xsl:for-each,因为您可能会重复使用模板,例如,如果您有多个编写者或导演太

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/movies">
<html>
    <head>
    <link rel="stylesheet" href="stylecss.css" />
        <title>My Movies Collection</title>
    </head>
    <body>
        <xsl:apply-templates select="movie" />
    </body>
</html>
</xsl:template>

<xsl:template match="movie">
    <h1>
        <xsl:value-of select="title" />
        <xsl:text> ( </xsl:text><xsl:value-of select="@year" /><xsl:text> ) </xsl:text>
    </h1>
    <p>
        <img src="{poster}"/>
        <span id="details">
            <xsl:text>Review: </xsl:text>
            <xsl:value-of select="@review" />
            <xsl:text>, Type: </xsl:text>
            <xsl:value-of select="@type" />
            <br></br>

            <xsl:text>Producer: </xsl:text>
            <xsl:apply-templates select="producer" />
            <br/>

            <xsl:text>Actor: </xsl:text>
            <xsl:apply-templates select="actor" />
            <br/>

            <xsl:text>Director: </xsl:text>
            <xsl:apply-templates select="director" />
            <br/>

            <i>         
                <xsl:text>Comments: </xsl:text>
                <xsl:value-of select="comments" />
            </i>
        </span>
    </p>
</xsl:template>

<xsl:template match="movie/*">
    <xsl:value-of select="."/> <br/>
</xsl:template>
</xsl:stylesheet>

还要注意在创建img元素

的src时使用属性值模板
<img src="{poster}"/>

花括号表示要计算的表达式,而不是字面输出。