XSLT - 列出位置问题

时间:2017-11-01 07:27:52

标签: xml xslt

我的输入xml包含多个列表,如下所示。

<listing>
    <item><p>abcd</p></item></listing>        
<listing>
    <item><p>abcd</p></item></listing>        
<listing>
    <item><p>abcd</p></item></listing>        
<listing>
    <item><p>abcd</p></item></listing>

输出应该是,

<listing id="p01" aid:pstyle="First" pagebreak="no">
<item><p>abcd</p>
</item>
</listing>        
<listing id="p02" aid:pstyle="Middle" pagebreak="no">
<item><p>abcd</p>
</item></listing>
<listing id="p03" aid:pstyle="Middle" pagebreak="no">
<item><p>abcd</p>
</item>
</listing>        
<listing id="p04" aid:pstyle="last" pagebreak="no">
<item><p>abcd</p>
</item></listing>

我的xslt就像,

<xsl:template match="listing">
    <xsl:choose>
        <xsl:when test="position()=1">
    <xsl:copy>
        <xsl:attribute name="id">
            <xsl:text>p</xsl:text>
            <xsl:number format="00" level="any"/>
        </xsl:attribute>
        <xsl:apply-templates select="@*"/>
        <xsl:attribute name="aid:pstyle">
<xsl:text>First</xsl:text>
        </xsl:attribute>
        <xsl:if test="not(attribute::pagebreak)">
            <xsl:attribute name="pagebreak">no</xsl:attribute>
        </xsl:if>
        <xsl:apply-templates select="node()"/>
    </xsl:copy>
        </xsl:when>            
        <xsl:when test="position()=last()">
            <xsl:copy>
                <xsl:attribute name="id">
                    <xsl:text>p</xsl:text>
                    <xsl:number format="00" level="any"/>
                </xsl:attribute>
                <xsl:apply-templates select="@*"/>
                <xsl:attribute name="aid:pstyle">
                    <xsl:text>last</xsl:text>
                </xsl:attribute>
                <xsl:if test="not(attribute::pagebreak)">
                    <xsl:attribute name="pagebreak">no</xsl:attribute>
                </xsl:if>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>                
        </xsl:when>
        <xsl:when test="parent::listing">
            <xsl:copy>
                <xsl:attribute name="id">
                    <xsl:text>p</xsl:text>
                    <xsl:number format="00" level="any"/>
                </xsl:attribute>
                <xsl:apply-templates select="@*"/>
                <xsl:attribute name="aid:pstyle">
                    <xsl:text>Level</xsl:text><xsl:value-of select="count(ancestor::listing)"/>
                </xsl:attribute>
                <xsl:if test="not(attribute::pagebreak)">
                    <xsl:attribute name="pagebreak">no</xsl:attribute>
                </xsl:if>
                <xsl:apply-templates select="node()"/>
            </xsl:copy>                
        </xsl:when>
        <xsl:otherwise>                
                <xsl:copy>
                    <xsl:attribute name="id">
                        <xsl:text>p</xsl:text>
                        <xsl:number format="00" level="any"/>
                    </xsl:attribute>
                    <xsl:apply-templates select="@*"/>
                    <xsl:attribute name="aid:pstyle">
                            <xsl:text>Middle</xsl:text>
                    </xsl:attribute>
                    <xsl:if test="not(attribute::pagebreak)">
                        <xsl:attribute name="pagebreak">no</xsl:attribute>
                    </xsl:if>
                    <xsl:apply-templates select="node()"/>
                </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>        
</xsl:template>

在使用上面的xslt时,我们没有将“pstyle”属性值更改为位置优先的“First”。我们得到的输出不正确,

<listing id="p01" aid:pstyle="Middle" pagebreak="no">
<item><p>abcd</p>
</item>
</listing>
<listing id="p02" aid:pstyle="Middle" pagebreak="no">
<item><p>abcd</p>
</item>
</listing>        
<listing id="p03" aid:pstyle="Middle" pagebreak="no">
<item><p>abcd</p>
</item>
</listing>        
<listing id="p04" aid:pstyle="last" pagebreak="no">
<item><p>abcd</p>
</item></listing>

请您指导我们,为什么这个xslt没有为位置1提供正确的值。

2 个答案:

答案 0 :(得分:1)

您可以尝试计数功能:

<xsl:template match="listing">
        <xsl:copy>
            <xsl:attribute name="id">
                <xsl:text>p</xsl:text>
                <xsl:number format="00" level="any"/>
            </xsl:attribute>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="aid:pstyle">
                <xsl:choose>
                    <xsl:when test="count(preceding::listing)=0">
                        <xsl:text>First</xsl:text>
                    </xsl:when>            
                    <xsl:when test="count(following::listing)=0">
                        <xsl:text>last</xsl:text>
                    </xsl:when>
                    <xsl:when test="parent::listing">
                        <xsl:text>Level</xsl:text><xsl:value-of select="count(ancestor::listing)"/>
                    </xsl:when>
                    <xsl:otherwise>                
                        <xsl:text>Middle</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:if test="not(attribute::pagebreak)">
                <xsl:attribute name="pagebreak">no</xsl:attribute>
            </xsl:if>
            <xsl:apply-templates select="node()"/>
        </xsl:copy>
    </xsl:template>

答案 1 :(得分:0)

xsl:template规则顶层的position()值是xsl:apply-templates选择的节点列表中匹配节点的位置。您还没有向我们展示xsl:apply-templates上的调用,这在这种情况下至关重要。如果您没有剥离空白文本节点,并且xsl:apply-templates选择了所有子节点,那么空白文本节点将包含在position()计数中,这意味着第一个列表element不是第一个节点。使用<xsl:apply-templates select="listing"/>,问题就会消失。