2013-10-18 134 views
4

我有一种情况,我需要检查可能连续编号的属性值,并在开始值和结束值之间输入破折号。检查连续编号的属性

<root> 
<ref id="value00008 value00009 value00010 value00011 value00020"/> 
</root> 

理想的产出将是...

8-11, 20 

我可以令牌化属性为独立的价值,但我不能确定如何检查是否在“valueXXXXX”末数为接连前一个值。

我使用XSLT 2.0

回答

4

您可以使用xsl:for-each-group@group-adjacent测试为number()值减去position()

这一招显然是由David Carlisle发明,according to Michael Kay.

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="2.0"> 
    <xsl:output indent="yes"/> 
    <xsl:template match="/"> 
     <xsl:variable name="vals" 
       select="tokenize(root/ref/@id, '\s?value0*')[normalize-space()]"/> 

     <xsl:variable name="condensed-values" as="item()*"> 

      <xsl:for-each-group select="$vals" 
           group-adjacent="number(.) - position()"> 
       <xsl:choose> 
        <xsl:when test="count(current-group()) > 1"> 
        <!--a sequence of successive numbers, 
         grab the first and last one and join with '-' --> 
        <xsl:sequence select=" 
           string-join(current-group()[position()=1 
               or position()=last()] 
              ,'-')"/> 
        </xsl:when> 
        <xsl:otherwise> 
         <!--single value group--> 
         <xsl:sequence select="current-group()"/> 
        </xsl:otherwise> 
       </xsl:choose> 
      </xsl:for-each-group> 
     </xsl:variable> 

     <xsl:value-of select="string-join($condensed-values, ',')"/> 

    </xsl:template> 
</xsl:stylesheet> 
+0

这是一个伟大的答案。有一件事对我来说是缺失的。我如何测试组是否是最后一项而不输出“,”? – Jeff

+0

它不应该有一个尾随逗号。你执行了它吗? string-join()将使用第二个字符串参数的值连接第一个参数中序列的值,并且不会附加到最后一个项目。 –

+0

我明白了。我必须修改我需要输出的内容。我需要将每个项目包装在单独的标记中,以便从执行中删除字符串连接。 – Jeff