以文本方式查看主题

-  中文XML论坛 - 专业的XML技术讨论区  (http://bbs.xml.org.cn/index.asp)
--  『 WORD to XML, HTML to XML 』  (http://bbs.xml.org.cn/list.asp?boardid=13)
----  xml 分组问题[求助]  (http://bbs.xml.org.cn/dispbbs.asp?boardid=13&rootid=&id=71219)


--  作者:hugh151721
--  发布时间:1/9/2009 11:33:00 AM

--  xml 分组问题[求助]
各位,我现在需要对XML进行分组显示,该用什么方式?
假设我的xml文件如下 :
<?xml version="1.0" standalone="yes"?>
<?xml:stylesheet type="text/xsl" href="group.xsl"?>
<NewDataSet>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>57.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00064</emp_no>
    <group_name>新光</group_name>
    <emp_name>刘</emp_name>
    <amt>15.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>48.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>22.0000</amt>
  </group>
</NewDataSet>

现在向进行分组显示,如:

1 00064 新光 刘 15.0000
-----------------------------------
1 00067 新光 张 57.0000
1 00067 新光 张 48.0000
1 00067 新光 张 22.0000


--  作者:宇义
--  发布时间:1/9/2009 1:23:00 PM

--  
http://bbs.xml.org.cn/dispbbs.asp?boardID=8&ID=70693
--  作者:hugh151721
--  发布时间:1/9/2009 1:37:00 PM

--  
谢谢宇义,xslt2.0 有新的 <for-each-group>,我使用了,但出现错误:
无法显示 XML 页。

使用 XSL 样式表无法查看 XML 输入。请更正错误然后单击 刷新按钮,或以后重试。


--------------------------------------------------------------------------------

关键字 xsl:template 可能不包含 xsl:for-each-group。
我的xsl是这样写的:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/02/xpath-functions" xmlns:xdt="http://www.w3.org/2005/02/xpath-datatypes">
  <xsl:template match="NewDataSet">
          <Table border="0.1" >
          <xsl:for-each-group select="group" group-by="@group_no">
     <tr>
                  <td>
                    <xsl:value-of select="group_no"/>
                  </td>
                  <td>
                    <xsl:value-of select="emp_no"/>
                  </td>
                  <td>
                    <xsl:value-of select="group_name"/>
                  </td>
                  <td>
                    <xsl:value-of select="emp_name"/>
                  </td>
                  <td>
                    <xsl:value-of select="amt"/>
                  </td>
                </tr>
          </xsl:for-each-group>
          </Table>
  </xsl:template>
</xsl:stylesheet>
请问哪里有错误?谢谢


--  作者:宇义
--  发布时间:1/9/2009 10:33:00 PM

--  
看样子你是用的是firefox吧?firefox不支持xslt2.0。目前还没有主流浏览器支持xslt2.0。所以只能使用xslt1.0和MUENCHIAN分组法了。
--  作者:Qr
--  发布时间:1/10/2009 11:32:00 AM

--  
用xsl:key可以解决这个问题,自己去看一下相关的用法吧。
--  作者:hugh151721
--  发布时间:1/10/2009 4:42:00 PM

--  
谢谢.我用是IE6.0测试的.不过也是不支持.看来只能用MUENCHIAN分组法了,现在用MUENCHIAN分组法我可以对一个key我可以解决,但是如果我想对分好组的下一层再次分组,该怎么解决.输出结果如:
key1   key2   value
a        001   123
a        001   154
a        001   254
a        002   247
a        002   175
b        001   475
b        001   571
b        003   245
b        003   541
既先对key1分组  再对key2分组
--  作者:hugh151721
--  发布时间:1/10/2009 4:44:00 PM

--  
呵呵,又来麻烦Qr板大了,对于一个key我现在已经能解决,用的是MUENCHIAN分组法,但是如果我想对分好组的下一层再次分组,该怎么解决.输出结果如:
key1   key2   value
a        001   123
a        001   154
a        001   254
a        002   247
a        002   175
b        001   475
b        001   571
b        003   245
b        003   541
既先对key1分组  再对key2分组
--  作者:Qr
--  发布时间:1/10/2009 5:54:00 PM

--  
试试这样嵌套(不过以下代码可是随便贴的,没有按语法规范来写,自己完善):
        <xsl:for-each select="key(a)">
                ...
                <xsl:for-each select="key(b)">
                        ...
                </xsl:for-each>
        </xsl:for-each>

--  作者:Qr
--  发布时间:1/10/2009 6:02:00 PM

--  
我还试过用XPath来解决这类问题,非常精典,但因U盘丢失,源码找不回来了。郁闷。
--  作者:hugh151721
--  发布时间:1/11/2009 9:56:00 PM

--  
我参照你的思想,写了一个xsl,但是有问题,能帮我看看吗.?
我的XML如下:

<?xml version="1.0" standalone="yes"?>
<?xml:stylesheet type="text/xsl" href="group.xsl"?>
<NewDataSet>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>57.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00064</emp_no>
    <group_name>新光</group_name>
    <emp_name>刘</emp_name>
    <amt>15.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>48.0000</amt>
  </group>
  <group>
    <group_no>1</group_no>
    <emp_no>00067</emp_no>
    <group_name>新光</group_name>
    <emp_name>张</emp_name>
    <amt>22.0000</amt>
  </group>
   <group>
    <group_no>2</group_no>
    <emp_no>00067</emp_no>
    <group_name>华春</group_name>
    <emp_name>张</emp_name>
    <amt>12.0000</amt>
  </group>
   <group>
    <group_no>2</group_no>
    <emp_no>00064</emp_no>
    <group_name>华春</group_name>
    <emp_name>刘</emp_name>
    <amt>25.0000</amt>
  </group>
   <group>
    <group_no>2</group_no>
    <emp_no>00068</emp_no>
    <group_name>华春</group_name>
    <emp_name>马</emp_name>
    <amt>23.0000</amt>
  </group>
   <group>
    <group_no>2</group_no>
    <emp_no>00067</emp_no>
    <group_name>华春</group_name>
    <emp_name>张</emp_name>
    <amt>24.0000</amt>
  </group>
</NewDataSet>


--  作者:hugh151721
--  发布时间:1/11/2009 9:56:00 PM

--  
这是我的XSL:
<?xml version="1.0" encoding="utf-8" ?>
- <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:key name="groupno" match="group" use="group_no" />
  <xsl:variable name="groupby1" select="group[generate-id(.)=generate-id(key('groupno',group_no))]" />
  <xsl:key name="group-by-emp" match="groupby1" use="emp_no" />
- <xsl:template match="NewDataSet">
- <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/tr/rec-html40">
- <Worksheet ss:Name="mypage">
- <Table border="1">
- <tr>
  <td>事业组编号</td>
  <td>员工代号</td>
  <td>事业组名称</td>
  <td>员工名称</td>
  <td>费用</td>
  </tr>
- <xsl:for-each select="$groupby1">
- <xsl:for-each select="group[generate-id(.)=generate-id(key('group-by-emp',emp_no))]">
- <xsl:for-each select="key('group-by-emp',emp_no)">
- <tr>
- <td>
  <xsl:value-of select="group_no" />
  </td>
- <td>
  <xsl:value-of select="emp_no" />
  </td>
- <td>
  <xsl:value-of select="group_name" />
  </td>
- <td>
  <xsl:value-of select="emp_name" />
  </td>
- <td>
  <xsl:value-of select="amt" />
  </td>
  </tr>
  </xsl:for-each>
  </xsl:for-each>
  </xsl:for-each>
- <tr>
  <td>合计</td>
  <td />
  <td />
  <td />
- <td>
  <xsl:value-of select="sum(//group/amt)" />
  </td>
  </tr>
  </Table>
  </Worksheet>
  </Workbook>
  </xsl:template>
  </xsl:stylesheet>
--  作者:hugh151721
--  发布时间:1/12/2009 9:32:00 AM

--  
我刚刚修改了我的xsl,如下:
<?xml version="1.0" encoding="utf-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:key   name="groupno"   match="group"   use="group_no"   />
  <xsl:key   name="empno"   match="group"   use="emp_no"   />
  <xsl:template match="NewDataSet">
      <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/tr/rec-html40">
        <Worksheet ss:Name="mypage">
          <Table border="1" >
            <tr>
              <td>事业组编号</td>
              <td>员工代号</td>
              <td >事业组名称</td>
              <td>员工名称</td>
              <td>费用</td>
            </tr>
            <xsl:for-each select="group[generate-id(.)=generate-id(key('groupno',group_no))]">
      <xsl:variable name="samegroup_no" select="key('groupno',group_no)" />
      <xsl:for-each select="$samegroup_no[not(emp_no=preceding-sibling::samegroup_no/emp_no)]">
     <xsl:variable name="sameemp_no" select="key('empno',emp_no)" />
      <xsl:for-each select ="$sameemp_no">
       <xsl:if test="$samegroup_no/group_no=group_no">
        <tr>
       <td>
        <xsl:value-of select="group_no"/>
       </td>
       <td>
        <xsl:value-of select="emp_no"/>
       </td>
        <td>
       <xsl:value-of select="group_name"/>
        </td>
        <td>
       <xsl:value-of select="emp_name"/>
        </td>
        <td>
       <xsl:value-of select="amt"/>
        </td>
      </tr>
      </xsl:if>
     </xsl:for-each>
     
     <tr>
      <th>ss</th>
     </tr>
     </xsl:for-each>
     <tr>
      <th>cc</th>
     </tr>
            </xsl:for-each>
            <tr>
              <td>合计</td>
              <td/>
              <td/>
              <td/>
              <td>
                  <xsl:value-of select="sum(//group/amt)"/>
              </td>
            </tr>
          </Table>
        </Worksheet>
      </Workbook>
  </xsl:template>
</xsl:stylesheet>
但得到的结果却不符合我的要求,结果为:

事业组编号 员工代号 事业组名称 员工名称 费用
1 00067 新光 张 57.0000
1 00067 新光 张 48.0000
1 00067 新光 张 22.0000
ss
1 00064 新光 刘 15.0000
ss
1 00067 新光 张 57.0000
1 00067 新光 张 48.0000
1 00067 新光 张 22.0000
ss
1 00067 新光 张 57.0000
1 00067 新光 张 48.0000
1 00067 新光 张 22.0000
ss
cc
2 00067 华春 张 12.0000
2 00067 华春 张 24.0000
ss
2 00064 华春 刘 25.0000
ss
2 00068 华春 马 23.0000
ss
2 00067 华春 张 12.0000
2 00067 华春 张 24.0000
ss
cc
合计    226
请问 “$samegroup_no[not(emp_no=preceding-sibling::samegroup_no/emp_no)] ”这句代码不是判断samegroup_no中的emp_no是不是第一次出现吗?


--  作者:Qr
--  发布时间:1/13/2009 3:30:00 PM

--  
随便写了一个eg,估计不能满足你的要求,但看你的几个xsl:for-each+key()嵌套偶就晕。
key()非常占用资源,如果XML信息量大的话,可能导致堆桟溢出。偶下面的代码只用一个key,外加一个sort已经够呛了。建议改写代码。

<?xml version="1.0" encoding="utf-8"?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
  <xsl:key   name="groupno"   match="group"   use="group_no"   />
  <xsl:template match="NewDataSet">
      <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/tr/rec-html40">
        <Worksheet ss:Name="mypage">
          <Table border="1" >
            <tr>
              <td>事业组编号</td>
              <td>员工代号</td>
              <td >事业组名称</td>
              <td>员工名称</td>
              <td>费用</td>
            </tr>
            <xsl:for-each select="group[generate-id(.)=generate-id(key('groupno',group_no))]">
<xsl:variable name="samegroup_no" select="group_no"/>
            <xsl:for-each select="key('groupno',group_no)">
  <xsl:sort select="emp_no"/>
<xsl:if test="$samegroup_no=group_no">

        <tr>
       <td>
        <xsl:value-of select="group_no"/>
       </td>
       <td>
        <xsl:value-of select="emp_no"/>
       </td>
        <td>
       <xsl:value-of select="group_name"/>
        </td>
        <td>
       <xsl:value-of select="emp_name"/>
        </td>
        <td>
       <xsl:value-of select="amt"/>
        </td>
      </tr>
</xsl:if>

            </xsl:for-each>
<tr><td>aaa</td></tr>
            </xsl:for-each>


            <tr>
              <td>合计</td>
              <td/>
              <td/>
              <td/>
              <td>
                  <xsl:value-of select="sum(//group/amt)"/>
              </td>
            </tr>
          </Table>
        </Worksheet>
      </Workbook>
  </xsl:template>
</xsl:stylesheet>


--  作者:Qr
--  发布时间:1/13/2009 4:08:00 PM

--  
给你个思路吧:
遍历所有节点,同时通过count()来统计与分组相关的节点,根据统计结果决定遍历与当前节点相关的节点,current()的用法比较关键。这种用法没有用到key和sort,特别是count()统计结果还可以大大减少循环的次数。

这是偶回忆9楼提过的源码所能给出的思路,不是很全面。

当然,模板递归+current() or key()、current()+key()的用法也不错,关键在算法,最好不要出现多个key(),sort(),多个current() (最好不超过两个)嵌套也不好。

这是偶当时测试相关代码的结论,一家之言,仅供参考。

因为最近在写些代码,没有太多时间来考虑和测试代码。

开动你的脑筋吧,XPath是关键。


--  作者:hugh151721
--  发布时间:1/13/2009 7:21:00 PM

--  
感谢Qr,后来我又稍微变换了下方式,分组的目的是达到了,主要代码如下:
---------------------------------------------------------------------------------------------------------
<xsl:key   name="groupno"   match="group"   use="group_no"   />
<xsl:key   name="empno"   match="group"   use="emp_no"   />

<xsl:for-each select="./group[generate-id(.)=generate-id(key('groupno',group_no))]"> 
<xsl:variable name="vargroup_no" select="group_no" /> 
<xsl:for-each select="../group[generate-id(.)=generate-id(key('empno',emp_no))]">       
<xsl:variable name="varemp_no" select="emp_no"/>     
<xsl:for-each select="../group[group_no=$vargroup_no and emp_no=$varemp_no]">
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
------------------------------------------------------------
不过我发现用这个方法,但数据量大时,效率就会很慢,我一个8M的XML文件,大概需要花2分钟。今天看了你的回复,回去再考虑考虑。再次感谢Qr斑大。


W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
140.625ms