XSLT for-each循环,其中每个节点是不同的元素

时间:2014-01-16 16:48:21

标签: xml xslt xpath for-loop

我正在为学校项目建立一个博客网站。博客文章的内容由许多元素组成,每个元素可以是纯文本,链接,图像或视频。所有这些元素必须按照它们在XML文件中存储的顺序显示,并且每个元素都将以新的<p>标记显示。

因此,我们的想法是以某种方式循环所有这些元素,每次迭代都应执行`xsl:choose来决定如何显示当前迭代的元素。

以此代码为例:当元素为b:blogPostContent/b:blogPostText类型时,如何使其仅执行TEXT部分,当元素为b:blogPostContent/b:blogPostLink时,如何使其执行LINK部分?

<xsl:for-each select="b:blogPostContent/*">
    <p>

        <!--TEXT-->
        <xsl:value-of select="."/>

        <!--LINK-->
        <xsl:element name="a">
            <xsl:attribute name="href">
                <xsl:value-of select="./@target"/>
            </xsl:attribute>
            <xsl:attribute name="target">
                _blank
            </xsl:attribute>
            <xsl:value-of select="."/>
        </xsl:element>

    </p>
</xsl:for-each> 

2 个答案:

答案 0 :(得分:1)

使用choose这样的元素:

<xsl:choose>
  <xsl:when test="name() = 'b:blogPostText'">
    <xsl:value-of select="."/>
  </xsl:when>
  <xsl:otherwise>
    <xsl:element name="a">
        <xsl:attribute name="href">
            <xsl:value-of select="./@target"/>
        </xsl:attribute>
        <xsl:attribute name="target">_blank</xsl:attribute>
        <xsl:value-of select="."/>
    </xsl:element>
  </xsl:otherwise>
</xsl:choose>

另一种可能性是在单独的模板中匹配这些元素。假设您的模板与b:blogPostContent元素匹配(实际上,您没有显示输入XML的结构):

<xsl:template match="b:blogPostContent">
   <p>
     <xsl:apply-templates select="b:blogPostText|b:blogPostLink"/>
   </p> 
</xsl:template>

<xsl:template match="b:blogPostText">
  <xsl:value-of select="."/>
</xsl:template>

<xsl:template match="b:blogPostLink">
  <a>
     <xsl:attribute name="href">
         <xsl:value-of select="./@target"/>
     </xsl:attribute>
     <xsl:attribute name="target">_blank</xsl:attribute>
     <xsl:value-of select="."/>
  </a>
</xsl:template>

请注意,<xsl:element name="a"><a>完全相同。这就是为什么我缩短了符号。 (无论如何,这是不一致的,因为你没有写<xsl:element name="p">)。

答案 1 :(得分:1)

  

因此,我们的想法是以某种方式循环所有这些元素,每次迭代都应执行xsl:choose来决定如何显示当前迭代的元素。

这个想法并不坏,但是受到强制性思维模式的驱使。 XSLT不是一种命令式语言,大多数时候最好遵循声明性模式。

<xsl:template match="b:blogPostContent">
  <article>
    <xsl:apply-templates select="*" mode="wrap_p" />
  </article>
</xsl:template>

<xsl:template select="*" mode="wrap_p">
  <p>
    <xsl:apply-templates select="." />
  </p>
</xsl:template>

<xsl:template match="b:blogPostText">
  <xsl:value-of select="." />
</xsl:template>

<xsl:template match="b:blogPostLink">
  <a href="{@target}" target="_blank">
    <xsl:value-of select="."/>
  </a>
</xsl:template>

<xsl:template match="b:blogPostList">
  <ul>
    <xsl:apply-templates select="*" />
  </ul>
</xsl:template>

等等。

通过这种方式,您可以获得小型,专用的模块化模板,这些模板仅执行一件事,而XSLT引擎决定哪个模板最适合哪个输入节点。


请注意,您永远不必编写<xsl:element><xsl:attribute>,除非您想动态创建它们(例如,基于变量的名称)。如果您想在输出中输入<a>,只需在XSLT中添加<a>