XSL for-each获取兄弟元素的内容

时间:2014-11-30 18:22:11

标签: xml xslt

我正在学习XML,并且正在进行一些我在网上找到的练习,并且很难处理一小块。我有以下XML,我想使用XSL转换为HTML。我在使用STAGEDIR元素时遇到了麻烦。它是SCENE的子元素,也是SPEECH的兄弟元素,我希望它出现在扬声器名称和他或她的行上方的HTML中。下面的代码会发生的情况是,每个SPEECH元素都会重复相同的STAGEDIR元素的第一个内容。相反,我想返回其兄弟SPEECH元素的前一个STAGEDIR元素的内容。

以下是XML的摘录

<PLAY>
    <TITLE>The Tragedy of Hamlet, Prince of Denmark</TITLE>
    <FM>
        <P>This work may be freely copied and distributed worldwide.</P>
    </FM>
    <ACT>
    <TITLE>ACT I</TITLE>

        <SCENE>
            <TITLE>SCENE I.  Elsinore. A platform before the castle.</TITLE>
            <STAGEDIR>FRANCISCO at his post. Enter to him BERNARDO</STAGEDIR>

            <SPEECH>
                <SPEAKER>BERNARDO</SPEAKER>
                <LINE>Who's there?</LINE>
            </SPEECH>
            <STAGEDIR>Enter HORATIO and MARCELLUS</STAGEDIR>

            <SPEECH>
            <SPEAKER>HORATIO</SPEAKER>
            <LINE>Friends to this ground.</LINE>
            </SPEECH>
        </SCENE>
    </ACT>
</PLAY>

以下是XSL

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" />

<xsl:template match="PLAY">
    <html>
        <head>
            <!--Head title is the play title-->
            <title><xsl:value-of select="TITLE" /></title>
        </head>
        <body>
            <div class="act">
                <xsl:for-each select="ACT">
                    <h2><xsl:value-of select="TITLE" /></h2>
                    <xsl:for-each select="SCENE">
                        <h3><xsl:value-of select="TITLE" /></h3>
                        <xsl:apply-templates select="SPEECH" />
                    </xsl:for-each>
                </xsl:for-each>
            </div>
        </body>
    </html>
</xsl:template>

    <xsl:template match="SPEECH">
    <xsl:for-each select=".">
        <xsl:if test="../STAGEDIR"> <!--THIS IS WHERE THE PROBLEM OCCURS-->
            <p><em><xsl:value-of select="../STAGEDIR" /></em></p>
        </xsl:if>
        <h4 style="color: red"><xsl:value-of select="SPEAKER" />:</h4>
        <p><xsl:if test="STAGEDIR">
            (<em><xsl:value-of select="STAGEDIR" /></em>)
        </xsl:if>
        <xsl:value-of select="LINE" /></p>
    </xsl:for-each>
</xsl:template>

以下是HTML的一小部分

<div class="act">

    <h2>ACT I</h2>
    <h3>SCENE I.  Elsinore. A platform before the castle.</h3>
    <p><em> FRANCISCO at his post. Enter to him BERNARDO</em></p>
    <h4 style="color: red"> BERNARDO:</h4>
    <p>Who's there? </p>
    <p><em>FRANCISCO at his post. Enter to him BERNARDO  </em></p>
</div>

正如您所看到的,<p><em>FRANCISCO at his post. Enter to him BERNARDO </em></p>正在重复。在XSL中,我如何像使用SPEECH元素在XSL中循环遍历元素并返回前一个兄弟元素的内容,在本例中为STAGEDIR。

1 个答案:

答案 0 :(得分:1)

对符合SPEECH

的模板进行以下调整
<xsl:template match="SPEECH">
    <xsl:if test="preceding-sibling::*[1]/self::STAGEDIR">
        <p>
           <em>
             <xsl:value-of select="preceding-sibling::*[1]/self::STAGEDIR" />
           </em>
       </p>
    </xsl:if>
    <h4 style="color: red"><xsl:value-of select="SPEAKER" />:</h4>
    <p><xsl:if test="STAGEDIR">
        (<em><xsl:value-of select="STAGEDIR" /></em>)
    </xsl:if>
    <xsl:value-of select="LINE" /></p>
</xsl:template>

生成以下输出HTML(仅提供相关部分):

 <div class="act">
     <h2>ACT I</h2>
     <h3>SCENE I.  Elsinore. A platform before the castle.</h3>
     <p><em>FRANCISCO at his post. Enter to him BERNARDO</em></p>
     <h4 style="color: red">BERNARDO:</h4>
     <p>Who's there?</p>
     <p><em>Enter HORATIO and MARCELLUS</em></p>
     <h4 style="color: red">HORATIO:</h4>
     <p>Friends to this ground.</p>
  </div>

<xsl:if test="preceding-sibling::*[1]/self::STAGEDIR">检查前面的第一个silbing是否为STAGEDIR元素。有关XPath轴的更多信息,您可以例如检查http://www.xmlplease.com/axis