3

拥有 XML Subversion 提交日志:

<?xml version="1.0"?>
<log>
<logentry
   revision="1236">
<author>me</author>
<date>2011-11-25T08:28:57.024571Z</date>
<msg>JIRA-5678: commit message</msg>
</logentry>
<logentry
   revision="1235">
<author>me</author>
<date>2011-11-25T08:28:47.024571Z</date>
<msg>JIRA-5678 - commit2 message</msg>
</logentry>
<logentry
   revision="1234">
<author>me</author>
<date>2011-11-25T08:28:37.024571Z</date>
<msg>JIRA-5678 commit3 message</msg>
</logentry>
</log>

我想生成一个按 JIRA 编号分组的报告,类似于这个:

<table>
<tr><th>revision</th><th>comment</th></tr>
<tr><td colspan=2>JIRA-5678</td></tr>
<tr><td>r1236</td><td>JIRA-5678: commit message</td></tr>
<tr><td>r1235</td><td>JIRA-5678 - commit2 message</td></tr>
<tr><td>r1234</td><td>JIRA-5678 commit3 message</td></tr>
</table>

提取 JIRA 编号并将其输出到单独列的转换:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">

<xsl:template match="/">
  <table summary="JIRAs">
    <tr>
      <th>JIRA#</th>
      <th>revision</th>
      <th>message</th>
    </tr>

  <xsl:for-each select="log/logentry[starts-with(msg,'JIRA-')]">
    <tr>
      <td><xsl:value-of select="fn:replace(msg,'^(JIRA-\d+).*$', '$1')" /></td>
      <td><xsl:value-of select="@revision" /></td>
      <td><xsl:value-of select="msg" /></td>
    </tr>
  </xsl:for-each>

  </table>
</xsl:template>

</xsl:stylesheet>

进行这种分组的 XSLT 代码是什么?

更新:我最终在 XML DOM 上编写了一个 python 脚本。如果您需要,请发表评论。

4

1 回答 1

5

I. 这个 XSLT 1.0 转换

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kEntryByNum" match="logentry" use="substring-before(msg, ':')"/>

 <xsl:template match="/*">
     <table>
       <tr><th>revision</th><th>comment</th></tr>

       <xsl:apply-templates select=
        "logentry
           [generate-id()
           =
            generate-id(key('kEntryByNum', substring-before(msg, ':'))[1])
           ]
      "/>
     </table>
 </xsl:template>

 <xsl:template match="logentry">
        <tr><td colspan="2"><xsl:value-of select="substring-before(msg, ':')"/></td></tr>
        <xsl:for-each select="key('kEntryByNum', substring-before(msg, ':'))">
            <tr>
                <td><xsl:value-of select="@revision"/></td>
                <td><xsl:value-of select="msg"/></td>
            </tr>
        </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当应用于以下 XML 文档时

<log>
    <logentry revision="1236">
        <author>me</author>
        <date>2011-11-25T08:28:57.024571Z</date>
        <msg>JIRA-5678: commit message</msg>
    </logentry>
    <logentry revision="1237">
        <author>me</author>
        <date>2011-11-25T08:28:57.024571Z</date>
        <msg>JIRA-5679: commit message</msg>
    </logentry>
    <logentry revision="1238">
        <author>me</author>
        <date>2011-11-25T08:28:57.024571Z</date>
        <msg>JIRA-5679: commit message</msg>
    </logentry>
    <logentry revision="1235">
        <author>me</author>
        <date>2011-11-25T08:28:47.024571Z</date>
        <msg>JIRA-5678: - commit2 message</msg>
    </logentry>
    <logentry revision="1234">
        <author>me</author>
        <date>2011-11-25T08:28:37.024571Z</date>
        <msg>JIRA-5678: commit3 message</msg>
    </logentry>
</log>

产生想要的正确结果

<table>
   <tr>
      <th>revision</th>
      <th>comment</th>
   </tr>
   <tr>
      <td colspan="2">JIRA-5678</td>
   </tr>
   <tr>
      <td>1236</td>
      <td>JIRA-5678: commit message</td>
   </tr>
   <tr>
      <td>1235</td>
      <td>JIRA-5678: - commit2 message</td>
   </tr>
   <tr>
      <td>1234</td>
      <td>JIRA-5678: commit3 message</td>
   </tr>
   <tr>
      <td colspan="2">JIRA-5679</td>
   </tr>
   <tr>
      <td>1237</td>
      <td>JIRA-5679: commit message</td>
   </tr>
   <tr>
      <td>1238</td>
      <td>JIRA-5679: commit message</td>
   </tr>
</table>

二、XSLT 2.0 解决方案

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kEntryByNum" match="logentry" use="substring-before(msg, ':')"/>

 <xsl:template match="/*">
     <table>
       <tr><th>revision</th><th>comment</th></tr>

       <xsl:for-each-group select="logentry" group-by="substring-before(msg, ':')">
         <xsl:apply-templates select="."/>
       </xsl:for-each-group>
     </table>
 </xsl:template>

 <xsl:template match="logentry">
        <tr><td colspan="2"><xsl:value-of select="substring-before(msg, ':')"/></td></tr>
        <xsl:for-each select="current-group()">
            <tr>
                <td><xsl:value-of select="@revision"/></td>
                <td><xsl:value-of select="msg"/></td>
            </tr>
        </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
于 2012-05-02T13:36:56.647 回答