XSLT:根据元素后代设置类

时间:2013-05-16 15:58:45

标签: xslt xpath xslt-1.0

我正在使用以下HTML上的XSL转换:

<div id="context">
    <p>Sometimes, there is content here.</p>
</div>

<div id="main-content">
    <p>There is always content here.</p>
</div>

<div id="related">
    <img src="CMS PREVIEW ICON - ADMIN ONLY"/>
    <p>Sometimes, there is content here.</p>
    <p>The image is always the first child only if the user is inside the CMS, but it should be ignored if there is not other content present.</p>
</div>

目前,我尝试调整main-content div和related div上的class属性,具体取决于related是否有任何后代(不是{ CMS图标)。这就是我所拥有的:

<xsl:template match="div[@id='main-content']">
    <xsl:copy>
        <!-- copy the current body node contents -->
        <xsl:attribute name="class">
            <xsl:choose>
                <xsl:when test="//div[@id='related']/descendant::* and name(//div[@id='related']/*[1]) != 'img' or count(//div[@id='related']/descendant::* > 1)  and name(//div[@id='related']/*[1]) != 'img'">span6</xsl:when>
                <!-- left nav but no right col -->
                <xsl:when test="not(//div[@id='related']/descendant::*) or (count(//div[@id='related']/descendant::* = 1) and name(//div[@id='related']/*[1]) = 'img')">span9</xsl:when>                    
                <!-- no left nav and populated right col -->
                <xsl:when test="//div[@id='related']/descendant::* and  (count(//div[@id='related']/descendant::* = 1) and name(//div[@id='related']/*[1]) != 'img') and not( //div[@class='data-entry wide'])">span9</xsl:when>                    
                <xsl:otherwise>span12</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
        <!-- output the rest -->
    </xsl:copy>
</xsl:template>

<xsl:template match="div[@id='related']">
    <xsl:copy>
        <!-- copy the current body node contents -->
        <xsl:attribute name="class">
            <xsl:choose>
                <xsl:when test="count(* = 0) or (count(* = 1) and name(*[1]) = 'img')">hidden</xsl:when>
                <xsl:when test="descendant::*">span3</xsl:when>
                <xsl:otherwise>hidden</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
        <!-- output the rest -->
    </xsl:copy>
</xsl:template>

然后,如果给related隐藏类,我会在以后删除它,这样它就不会占用带宽,DOM空间等。

我认为这样可以正常工作,因为它似乎在xpath中获得了正确的值,但它并没有像它应该那样删除元素。这有点奇怪,因为我需要知道:

  1. related中是否包含不在CMS内的视图的后代
  2. AND,对于CMS内部的视图,是否存在不是特定图像的后代(其他图像将始终包含在div,链接等中)。
  3. 有什么想法吗?

    谢谢, 乔纳森

1 个答案:

答案 0 :(得分:2)

即使我不完全确定我是否对您的请求有正确的理解,我也会尝试一下。

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

        <xsl:template match="div[@id='main-content']">
    <xsl:copy>
        <!-- copy the current body node contents -->
        <xsl:attribute name="class">
            <xsl:choose>
                <!-- "related" has any descendants (that are not the CMS icon). -->
                <xsl:when test="//div[@id='related']/* and 
                          count(//div[@id='related']/img)  !=  count(//div[@id='related']/*) ">span6</xsl:when>
                <xsl:otherwise>span9</xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
        <!-- output the rest -->
    </xsl:copy>
</xsl:template>

<xsl:template match="div[@id='related']">
    <xsl:copy>
        <!-- copy the current body node contents -->
        <xsl:apply-templates select="@*"/>
        <xsl:choose>
                <!-- it should be ignored if there is not other content present -->
                <xsl:when test=" count(img) = count(*)">
                    <xsl:attribute name="class">hidden</xsl:attribute>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:attribute name="class">span3</xsl:attribute>
                    <xsl:apply-templates select="node()"/>

                </xsl:otherwise>
            </xsl:choose>
        <!-- output the rest -->
    </xsl:copy>
</xsl:template>

    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates  select="node() | @*" />
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>