如何将一系列图像转换为幻灯片显示,将单个图像转换为嵌入式图像?

迈克尔·Shopsin

我需要xslt将使用<media>标记作为幻灯片显示的一系列图像以及将单个图像作为嵌入式图像使用。我有逻辑可以找到<media><p>标签包围的逻辑,但是将其扩展为处理所有非<media>标签是很乏味的。如何编写not(p)在xslt 1.0中有效的某种逻辑?

这是xslt(我删除了完整的调用模板代码,因为它并不重要):

<xsl:template name="textImage">
        <xsl:param name="paragraphs"/>
        <xsl:variable name="paragraphCount" select="count($paragraphs)"/>
        <xsl:for-each select="$paragraphs">
            <xsl:choose>
                <xsl:when test="mediaReference">
                    <xsl:choose>
                        <!--single media block-->
                        <xsl:when test="ancestor::table or position() = $paragraphCount or (position() = 1 and (generate-id(following-sibling::*[1]) != generate-id(following-sibling::media[1]))) or (generate-id(preceding-sibling::p[1]/following-sibling::media[1]) = generate-id(current()) and generate-id(following-sibling::p[1]/preceding-sibling::media[1]) = generate-id(current()))">
                            <xsl:call-template name="imageNode"/>
                        </xsl:when>
                        <!--two more pam:media blocks for a carousel-->
                        <xsl:otherwise>
                            <xsl:choose>
                                <xsl:when test="generate-id(preceding-sibling::p[1]/following-sibling::media[1]) = generate-id(current())">
                                    <xsl:call-template name="firstImageNode"/>
                                </xsl:when>
                                <xsl:when test="generate-id(following-sibling::p[1]/preceding-sibling::media[1]) = generate-id(current())">
                                    <xsl:call-template name="lastImageNode"/>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:call-template name="imageNode"/>
                                </xsl:otherwise>
                            </xsl:choose>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="textNode"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>

这是一些示例xml:

<?xml version="1.0" encoding="utf-8"?>
<message>
    <article xml:lang="en-US">
        <body>
            <h2>What a Chicken!</h2>
            <media>
                <mediaReference refid="BA_chicken1.jpg"/>
            </media>
            <ol>
                <li>
                    <p>Place chicken breast side down.</p>
                </li>
            </ol>
            <media>
                <mediaReference refid="BA_chicken2.jpg"/>
            </media>
            <media>
                <mediaReference refid="BA_chicken3.jpg"/>
            </media>
            <p>More about chickens</p>
            <media>
                <mediaReference refid="BA_chicken4.jpg"/>
            </media>
            <p>The End</p>
        </body>
    </article>
</message>

正确的输出如下所示:

<h2>What a Chicken!</h2>
<img src="BA_chicken1.jpg">
<ol><li>
    <p>Place chicken breast side down.</p>
</li></ol>
<div class="slideshow">
    <img src="BA_chicken2.jpg">
    <img src="BA_chicken3.jpg">
</div>
<p>More about chickens</p>
<img src="BA_chicken4.jpg">
<p>The End</p>
C队

也许您将从更好地利用匹配模板的方法中受益。如果从身份模板开始,则将有单独的模板来匹配您的各种情况,例如它是一个单独的还是一组的,对于连续的模板,您将具有一个递归模板来一次处理一个连续的元素。

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:pam="pam">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <!-- Ignore media elements with direct preceding siblings as these are processed elsewhere -->
    <xsl:template match="pam:media[preceding-sibling::*[1][self::pam:media]]" priority="2" />

    <!-- First of a group -->
    <xsl:template match="pam:media[following-sibling::*[1][self::pam:media]]">
      <div class="image">
          <xsl:apply-templates select="self::*" mode="image" />
      </div>
    </xsl:template>

    <!-- Individual -->
    <xsl:template match="pam:media">
        <xsl:apply-templates select="self::*" mode="image" />
    </xsl:template>

    <!-- Template that actually creates the image -->
    <xsl:template match="pam:media" mode="image">
        <img src="{pam:mediaReference/@pam:refid}" />
        <xsl:apply-templates select="following-sibling::*[1][self::pam:media]" mode="image" />
    </xsl:template>

    <!-- Identity Template -->
    <xsl:template match="@*|node()" name="identity">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我注意到您的XSLT似乎可以区分组中的第一个元素和最后一个元素,尽管您的输出XML并未显示此内容。调整此答案以解决此问题的一种方法是修改“图像”模式模板以保持运行计数,以允许其检查它是组中的第一个节点还是最后一个节点。

例如,此更新的模板在第一个和最后一个元素上添加了一个不同的类:

<xsl:template match="pam:media" mode="image">
    <xsl:param name="position" select="1" />
    <xsl:variable name="nextElement" select="following-sibling::*[1][self::pam:media]" />
    <img src="{pam:mediaReference/@pam:refid}">
        <xsl:attribute name="class">
        <xsl:choose>
            <xsl:when test="$position = 1 and $nextElement">first image</xsl:when>
            <xsl:when test="$position > 1 and not($nextElement)">last image</xsl:when>
            <xsl:otherwise>image</xsl:otherwise>
        </xsl:choose>
        </xsl:attribute>
    </img>
    <xsl:apply-templates select="$nextElement" mode="image">
        <xsl:with-param name="position" select="$position + 1" />
    </xsl:apply-templates>
</xsl:template>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章