在XSLT1中,如何按节点值的三个级别对XML节点进行分组?
我是XSLT新手。我一直在这里阅读XSLT文档和其他帖子。我被困了一段时间,不知道下一步该怎么办。 原始XML:在XSLT1中,如何按节点值的三个级别对XML节点进行分组?,xml,transform,xslt-1.0,Xml,Transform,Xslt 1.0,我是XSLT新手。我一直在这里阅读XSLT文档和其他帖子。我被困了一段时间,不知道下一步该怎么办。 原始XML: <?xml version="1.0" encoding="UTF-8"?> <COVERAGE> <FILE> <RUNDATE>2014-04-16</RUNDATE> <RUNTIME>20:11:20</RUNTIME> <GROU
<?xml version="1.0" encoding="UTF-8"?>
<COVERAGE>
<FILE>
<RUNDATE>2014-04-16</RUNDATE>
<RUNTIME>20:11:20</RUNTIME>
<GROUPID1>GROUP ID1</GROUPID1>
<GROUPID2>GROUP ID2</GROUPID2>
<USERID>ABC</USERID>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<OV>N</OV>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<OV>N</OV>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<OV>N</OV>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</FILE>
<FILE>
<RUNDATE>2014-04-16</RUNDATE>
<RUNTIME>20:12:16</RUNTIME>
<GROUPID1>GROUP ID3</GROUPID1>
<GROUPID2>GROUP ID4</GROUPID2>
<USERID>BDF</USERID>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<OV>Y</OV>GOV>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<OV>N</OV>GOV>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<OV>N</OV>GOV>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</FILE>
<FILE>
<RUNDATE>2014-04-16</RUNDATE>
<RUNTIME>20:12:16</RUNTIME>
<GROUPID1>GROUP ID3</GROUPID1>
<GROUPID2>GROUP ID4</GROUPID2>
<USERID>BDF</USERID>
<MODULE>
<NAME>Module2</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<OV>Y</OV>GOV>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<OV>N</OV>GOV>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<TYPE>1</TYPE>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<OV>N</OV>GOV>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</FILE>
</COVERAGE>
首先,如果MODULE/NAME、UNIT/UNITDATE、UNIT/UNITTIME、CSECT/EXTNAME相同,则将已执行和未执行的节点分组在一起
转换后的XML应如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<COVERAGE>
<FILE>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED><EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</FILE>
<FILE>
<MODULE>
<NAME>Module2</NAME>
<UNIT>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
<UNIT>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</FILE>
</COVERAGE>
这是我阅读后得到的XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="moduleKey" match="MODULE" use="NAME" />
<xsl:key name="unitKey" match="UNIT" use="concat(CSECT/EXTNAME, '_', UNITDATE,'_',UNITTIME)" />
<xsl:template match="COVERAGE">
<COVERAGE>
<xsl:for-each select="FILE">
<FILE>
<RUNDATE>
*
</RUNDATE>
<RUNTIME>
*
</RUNTIME>
<GROUPID1>
*
</GROUPID1>
<GROUPID2>
*
</GROUPID2>
<USERID>
*
</USERID>
<xsl:for-each select="MODULE[count( . | key('moduleKey', NAME)[1]) = 1]">
<MODULE>
<NAME>
<xsl:value-of select="NAME" />
</NAME>
<xsl:for-each select="UNIT[count( . | key('unitKey', concat(CSECT/EXTNAME, '_', UNITDATE,'_',UNITTIME))[1]) = 1]">
<UNIT>
<TYPE>
<xsl:value-of select="TYPE" />
</TYPE>
<UNITDATE>
<xsl:value-of select="COMPILEDATE" />
</UNITDATE>
<UNITTIME>
<xsl:value-of select="COMPILETIME" />
</UNITTIME>
<CSECT>
<EXTNAME>
<xsl:value-of select="CSECT/EXTNAME" />
</EXTNAME>
<OV>
*
</OV>
<xsl:copy-of select="key('unitKey', concat(CSECT/EXTNAME, '_', UNITDATE,'_',UNITTIME))/CSECT/EXECUTED" />
<xsl:copy-of select="key('unitKey', concat(CSECT/EXTNAME, '_', UNITDATE,'_',UNITTIME))/CSECT/UNEXECUTED" />
</CSECT>
</UNIT>
</xsl:for-each>
</MODULE>
</xsl:for-each>
</FILE>
</xsl:for-each>
</COVERAGE>
</xsl:template>
</xsl:stylesheet>
但是这个XSL不能产生我们想要的东西。多谢各位
首先,将已执行和未执行的节点分组在一起
如果MODULE/NAME、UNIT/UNITDATE、UNIT/UNITTIME、CSECT/EXTNAME是
一样
我在您的输出中看不到这一点——可能是因为它对于一个如此复杂的问题来说太复杂了。在任何情况下,如果这是您想要的,您应该使用连接组的四个特征的单个键
例如,以下样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="sect" match="CSECT" use="concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME)"/>
<xsl:template match="/">
<COVERAGE>
<!-- FOR EACH DISTINCT GROUP -->
<xsl:for-each select="COVERAGE/FILE/MODULE/UNIT/CSECT[count(. | key('sect', concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME))[1]) = 1]">
<MODULE>
<NAME><xsl:value-of select="../../NAME"/></NAME>
<UNIT>
<UNITDATE><xsl:value-of select="../UNITDATE"/></UNITDATE>
<UNITTIME><xsl:value-of select="../UNITTIME"/></UNITTIME>
<CSECT>
<EXTNAME><xsl:value-of select="EXTNAME"/></EXTNAME>
<!-- GET RECORDS IN CURRENT GROUP -->
<xsl:for-each select="key('sect', concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME))">
<xsl:copy-of select="EXECUTED | UNEXECUTED"/>
</xsl:for-each>
</CSECT>
</UNIT>
</MODULE>
</xsl:for-each>
</COVERAGE>
</xsl:template>
</xsl:stylesheet>
应用于输入时,将产生以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<COVERAGE>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
<MODULE>
<NAME>Module1</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
<MODULE>
<NAME>Module2</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITA</EXTNAME>
<EXECUTED>43.1 46.1 47.1 50.1 51.1 52.1 56.1 58.1 63.1 65.1</EXECUTED>
<EXECUTED>73.1 74.1 75.1 78.1 79.1</EXECUTED>
<UNEXECUTED>60.1 70.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
<MODULE>
<NAME>Module2</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITB</EXTNAME>
<EXECUTED>32.1 36.1 37.1 38.1 44.1 50.1 56.1 57.1 58.1</EXECUTED>
<UNEXECUTED>40.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
<MODULE>
<NAME>Module2</NAME>
<UNIT>
<UNITDATE>2014-03-14</UNITDATE>
<UNITTIME>15:15:00</UNITTIME>
<CSECT>
<EXTNAME>UNITC</EXTNAME>
<EXECUTED>32.1 34.1 35.1 38.1 39.1 43.1 44.1 51.1 52.1 53.1</EXECUTED>
<EXECUTED>59.1 60.1</EXECUTED>
<UNEXECUTED>46.1 55.1</UNEXECUTED>
</CSECT>
</UNIT>
</MODULE>
</COVERAGE>
编辑:
每个文件节点有一个模块节点,一个模块节点有多个单元
节点,每个单元节点一个CSNEXT节点,每个CSNEXT节点有多个
已执行或未执行的节点
好吧,但你没有告诉我们如何将他们分组。通过查看输出文件很难判断,除非你想花几个小时比较输入和输出。即使这样,答案也不完全清楚,因为您的输出肯定是错误的:此节点:
<UNEXECUTED>60.1 70.1</UNEXECUTED>
在输出中显示四次-但在输入中仅显示三次
我猜您需要以下内容,即先按模块分组,即按文件/模块分组,然后按CSECT分组,即按单元/CSECT分组:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="module" match="MODULE" use="NAME"/>
<xsl:key name="sect" match="CSECT" use="concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME)"/>
<xsl:template match="/">
<COVERAGE>
<!-- FOR EACH DISTINCT MODULE -->
<xsl:for-each select="COVERAGE/FILE/MODULE[count(. | key('module', NAME)[1]) = 1]">
<FILE>
<MODULE>
<NAME><xsl:value-of select="NAME"/></NAME>
<!-- FOR EACH DISTINCT CSECT -->
<xsl:for-each select="UNIT/CSECT[count(. | key('sect', concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME))[1]) = 1]">
<UNIT>
<CSECT>
<EXTNAME><xsl:value-of select="EXTNAME"/></EXTNAME>
<!-- GET RECORDS IN CURRENT GROUP -->
<xsl:for-each select="key('sect', concat(../../NAME, '_', ../UNITDATE, '_', ../UNITTIME, '_', EXTNAME))">
<xsl:copy-of select="EXECUTED | UNEXECUTED"/>
</xsl:for-each>
</CSECT>
</UNIT>
</xsl:for-each>
</MODULE>
</FILE>
</xsl:for-each>
</COVERAGE>
</xsl:template>
</xsl:stylesheet>
谢谢你的回复。但是模块节点不再分组在一起。请查看原始XML文件。@kelly66我恐怕不知道这是什么意思。我建议您1最小化XML输入文件,只显示这个问题所需的内容;2以类似的方式修复输出文件,目前它完全不可理解;用这么多的话来解释请求转换背后的逻辑是什么。到目前为止,你所说的都是我在回答开始时引用的内容——这正是我的建议的作用。对不起,迈克尔,英语不是我的第一语言。我修改了我希望转换成的XML。更容易理解。希望你明白我的意思。基本上,XML结构是:每个文件节点有一个模块节点,一个模块节点有多个单元节点,每个单元节点有一个CSNEXT节点,每个CSNEXT节点有许多已执行或未执行的节点。谢谢你的帮助,迈克尔@kelly66查看对我的帖子的编辑我认为你的英语不是这里的问题。非常感谢你,迈克尔,好好工作吧。我的第一篇文章在这里,但学到了很多。再次感谢你。