我正在学习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。
答案 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