我有一个xml文件,如下所示,
<session>
<p>Cricket<s/><s/><s/><s/> was first played England<s/> in or before the<s/><s/> 16th century.</p>
<p>By the end of<s/><s/><s/> the 18th century, it had developed <s/><s/>to be the national sport of England.</p>
<p>The expansion<s/><s/> of the British Empire led to cricket<s/><s/><s/><s/><s/> being played overseas and by the mid-19th century</p>
</session>
<s>
个节点内有<p>
个节点。我的目标是计算连续的<s>
个节点,并将计数作为<s>
个节点中的属性。
所以输出应如下所示,
<session>
<p>Cricket<s count="4"/> was first played in southern England<s count="1"/> in or before the<s count="2"/> 16th century.</p>
<p>By the end of<s count="3"/> the 18th century, it had developed <s count="2"/>to be the national sport of England.</p>
<p>The expansion<s count="2"/> of the British Empire led to cricket<s count="5"/> being played overseas and by the mid-19th century</p>
</session>
我是XSLT的新手,我想不出任何逻辑我怎么能完成这项任务。 你能告诉我怎样才能做到这一点?
答案 0 :(得分:1)
xslt 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- template for s not directly preceded by s -->
<xsl:template match="s[preceding-sibling::node()[1][not(self::s)]]">
<s>
<xsl:attribute name="count">
<xsl:call-template name="count">
<xsl:with-param name="ctx" select="."/>
<xsl:with-param name="ret" select="1"/>
</xsl:call-template>
</xsl:attribute>
</s>
</xsl:template>
<!-- do nothing with other s -->
<xsl:template match="s[preceding-sibling::node()[1][self::s]]"/>
<!-- calculate the number of adjacent s -->
<xsl:template name="count">
<xsl:param name="ctx"/>
<xsl:param name="ret"/>
<xsl:choose>
<xsl:when test="$ctx/following-sibling::node()[1][self::s]">
<xsl:call-template name="count">
<xsl:with-param name="ctx" select="$ctx/following-sibling::s[1]"/>
<xsl:with-param name="ret" select="$ret + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$ret"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
假设使用XSLT 2.0,您可以使用for-each-group select="node()" group-adjacent="boolean(self::s)"
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p[s]">
<xsl:copy>
<xsl:for-each-group select="node()" group-adjacent="boolean(self::s)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<s count="{count(current-group())}"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>