首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分组和sorting....how?

分组和sorting....how?
EN

Stack Overflow用户
提问于 2010-09-24 04:15:40
回答 3查看 7.9K关注 0票数 3

我有一个看起来像下面这样的XML文件...

代码语言:javascript
复制
    <states>
 <state>
  <name>North Carolina</name>
  <city>Charlotte</city>
 </state>
 <state>
  <name>Alaska</name>
  <city>Fairbanks</city>
 </state>
 <state>
  <name>Virginia</name>
  <city>Leesburg</city>
 </state>
 <state>
  <name>Alaska</name>
  <city>Coldfoot</city>
 </state>
 <state>
  <name>North Carolina</name>
  <city>Harrisburg</city>
 </state>
 <state>
  <name>Virginia</name>
  <city>Ashburn</city>
 </state>  
</states>

我需要产生一份报告,列出每个州,是字母顺序与每个城市以下....例如..

代码语言:javascript
复制
Alaska - Fairbanks, Coldfoot
North Carolina - Charlotte, Harrisburg
Virginia - Leesburg, Ashburn

(城市不必按字母顺序排列,只需按州排列)

我试图通过对state/state执行for-each来解决这个问题,按名称对其进行排序并对其进行处理。像这样....

代码语言:javascript
复制
    <xsl:for-each select="states/state">
       <xsl:sort select="name" data-type="text" order="ascending"/>
       <xsl:value-of select="name"/>-<xsl:value-of select="city"/>
    </xsl:for-each>   

这给了我...

代码语言:javascript
复制
 Alaska - Fairbanks
 Alaska - Coldfoot
 North Carolina - Charlotte
 North Carolina - Harrisburg
 Virginia - Leesburg
 Virginia - Ashburn

排序成功了,现在我想分组。我能想到的唯一一件事就是与之前的状态进行比较,因为它是排序的,所以它应该能识别状态值是否没有改变。像这样..。

代码语言:javascript
复制
<xsl:for-each select="states/state">
             <xsl:sort select="name" data-type="text" order="ascending"/>
  <xsl:variable name="name"><xsl:value-of select="name">
  <xsl:variable name="previous-name"><xsl:value-of select="(preceding-sibling::state)/name">
  <xsl:if test="$name != $previous-name">
   <br/><xsl:value-of select="name"/>-
  </xsl:if>
  <xsl:value-of select="city"/>
 </xsl:for-each>

可悲的是,前面的兄弟特征似乎不能很好地与排序一起工作,所以,在第一次通过(在第一个阿拉斯加)时,它将第一个北卡罗来纳州视为前面的兄弟。这导致了一些奇怪的结果,这完全不是我喜欢的。

所以,我使用的是XSLT1.0...有什么想法/建议吗?

谢谢

EN

回答 3

Stack Overflow用户

发布于 2010-09-24 04:52:36

此样式表:

代码语言:javascript
复制
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kStateByName" match="state" use="name"/>
    <xsl:output method="text"/>
    <xsl:template match="/">
        <xsl:apply-templates
                   select="/*/state[count(.|key('kStateByName',name)[1])=1]">
            <xsl:sort select="name"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="state">
        <xsl:value-of select="concat(name,' - ')"/>
        <xsl:apply-templates select="key('kStateByName',name)/city"/>
    </xsl:template>
    <xsl:template match="city">
        <xsl:value-of select="concat(.,substring(', ', 
                                                 1 div (position()!=last())),
                                       substring('&#xA;',
                                                 1 div (position()=last())))"/>
    </xsl:template>
</xsl:stylesheet>

输出:

代码语言:javascript
复制
Alaska - Fairbanks, Coldfoot
North Carolina - Charlotte, Harrisburg
Virginia - Leesburg, Ashburn

注释:按州的名称分组。分隔符子串表达式仅适用于拉入样式(将模板应用于城市)

XSLT 2.0解决方案:

代码语言:javascript
复制
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="states">
        <xsl:for-each-group select="state" group-by="name">
            <xsl:sort select="name"/>
            <xsl:value-of select="concat(name,
                                         ' - ',
                                         string-join(current-group()/city,', '),
                                         '&#xA;')"/>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

只是为了好玩,下面这个XPath 2.0表达式:

代码语言:javascript
复制
string-join(for $state in distinct-values(/*/*/name)
            return concat($state,
                          ' - ',
                          string-join(/*/*[name=$state]/city,
                                      ', ')),
            '&#xA;')
票数 5
EN

Stack Overflow用户

发布于 2010-09-24 04:23:46

对于XSLT1.0中的分组,您可能必须使用Muenchian Method。它可能很难理解,但一旦你让它工作了,你就应该可以开始工作了。

票数 1
EN

Stack Overflow用户

发布于 2010-09-24 06:10:42

这将返回一个不同的状态列表:

代码语言:javascript
复制
  <xsl:for-each select="states/state">
     <xsl:sort select="name" />
     <xsl:if test="not(name = preceding-sibling::state/name)" >
         <xsl:value-of select="name" />
     </xsl:if>
  </xsl:for-each>

我使用了您的示例XML,用上面的代码构建了一个小样式表,通过Xalan-j运行它,它返回:

阿拉斯加北卡罗来纳州弗吉尼亚州

因此,您应该能够应用一个模板或另一个for-each循环来拉取每个不同州的城市列表。

克里斯

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3782219

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档