2010-11-25 27 views
1

我能够写一个可怕的糟糕的xslt没有使用键,但它是非常缓慢和凌乱。有谁知道我会如何将下面的XML文件转换成干净的预期结果?谢谢!我怎样才能转换这个使用键

输入:

<testExecution> 
    <test> 
     <test.1/> 
     <test.2/> 
     <test.3/> 
    </test> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <executor> 
     <executor.1/> 
     <executor.2/> 
     <executor.3/> 
    </executor> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <invoker> 
     <invoker.1/> 
     <invoker.2/> 
     <invoker.3/> 
    </invoker> 
    <recipient> 
     <recipient.1/> 
     <recipient.2/> 
     <recipient.3/> 
    </recipient> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
</testExecution> 

结果:

<testExecution> 
    <test> 
     <test.1/> 
     <test.2/> 
     <test.3/> 
    </test> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <people> 
     <importantPeople> 
      <executor> 
       <executor.1/> 
       <executor.2/> 
       <executor.3/> 
      </executor> 
      <comment> 
       <comment.1/> 
       <comment.2/> 
       <comment.3/> 
      </comment> 
      <comment> 
       <comment.1/> 
       <comment.2/> 
       <comment.3/> 
      </comment> 
     </importantPeople> 
     <invoker> 
      <invoker.1/> 
      <invoker.2/> 
      <invoker.3/> 
     </invoker> 
    </people> 
    <recipient> 
     <recipient.1/> 
     <recipient.2/> 
     <recipient.3/> 
    </recipient> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
</testExecution> 
+0

好问题,+1。请参阅我的答案,了解使用和覆盖身份规则的传统XSLT解决方案,并为以下“注释”使用密钥。 – 2010-11-26 00:36:57

回答

4

该样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:key name="kElementByTest" match="invoker|recipient" 
      use="generate-id(preceding-sibling::test[1])"/> 
    <xsl:template match="node()|@*" name="identity"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()[1]|@*"/> 
     </xsl:copy> 
     <xsl:apply-templates select="following-sibling::node()[1]"/> 
    </xsl:template> 
    <xsl:template match="executor"> 
     <xsl:variable name="vFollowing" 
         select="key('kElementByTest', 
            generate-id(preceding-sibling::test[1]))"/> 
     <people> 
      <importantPeople> 
       <xsl:call-template name="identity"/> 
      </importantPeople> 
      <xsl:apply-templates select="$vFollowing/self::invoker" 
            mode="copy"/> 
     </people> 
     <xsl:apply-templates select="$vFollowing/self::recipient" 
          mode="copy"/> 
    </xsl:template> 
    <xsl:template match="invoker"/> 
    <xsl:template match="recipient"/> 
    <xsl:template match="node()" mode="copy"> 
     <xsl:call-template name="identity"/> 
    </xsl:template> 
</xsl:stylesheet> 

输出:

<testExecution> 
    <test> 
     <test.1></test.1> 
     <test.2></test.2> 
     <test.3></test.3> 
    </test> 
    <comment> 
     <comment.1></comment.1> 
     <comment.2></comment.2> 
     <comment.3></comment.3> 
    </comment> 
    <people> 
     <importantPeople> 
      <executor> 
       <executor.1></executor.1> 
       <executor.2></executor.2> 
       <executor.3></executor.3> 
      </executor> 
      <comment> 
       <comment.1></comment.1> 
       <comment.2></comment.2> 
       <comment.3></comment.3> 
      </comment> 
      <comment> 
       <comment.1></comment.1> 
       <comment.2></comment.2> 
       <comment.3></comment.3> 
      </comment> 
     </importantPeople> 
     <invoker> 
      <invoker.1></invoker.1> 
      <invoker.2></invoker.2> 
      <invoker.3></invoker.3> 
     </invoker> 
    </people> 
    <recipient> 
     <recipient.1></recipient.1> 
     <recipient.2></recipient.2> 
     <recipient.3></recipient.3> 
    </recipient> 
    <comment> 
     <comment.1></comment.1> 
     <comment.2></comment.2> 
     <comment.3></comment.3> 
    </comment> 
    <comment> 
     <comment.1></comment.1> 
     <comment.2></comment.2> 
     <comment.3></comment.3> 
    </comment> 
</testExecution> 

注意:细粒度遍历。 “仅用于此测试”的关键字如下。用于“关闭此级别”的空模板。推式“继续处理”模式。它可以是完整的“拉式”匹配“标志前的前一个”。

+0

真棒谢谢! – user364939 2010-11-26 01:18:39

1

此转换使用并覆盖身份规则。使用key()函数检索紧接在executor之后的注释。 executor,invokercomment紧跟在executor后面的是专用模式,名称为people。在通常的,匿名模式这些被空模板匹配,以避免它们复制的第二时间:

<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="kExecComments" match= 
    "comment 
      [preceding-sibling::* 
       [not(self::comment)][1] 
         [self::executor] 
      ]" 
    use="generate-id(preceding-sibling::executor[1])"/> 

<xsl:template match="node()|@*" name="identity"> 
    <xsl:copy> 
    <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="executor"> 
    <people> 
    <importantPeople> 
     <xsl:apply-templates mode="people" 
     select=".|key('kExecComments', generate-id())"/> 
    </importantPeople> 
    <xsl:apply-templates mode="people" select= 
    "following-sibling::invoker"/> 
    </people> 
</xsl:template> 

<xsl:template match="executor|comment|invoker" 
     mode="people"> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match= 
    "invoker | 
    comment 
      [preceding-sibling::* 
       [not(self::comment)][1] 
         [self::executor] 
      ]"/> 

</xsl:stylesheet> 

当所提供的XML文档施加:

<testExecution> 
    <test> 
     <test.1/> 
     <test.2/> 
     <test.3/> 
    </test> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <executor> 
     <executor.1/> 
     <executor.2/> 
     <executor.3/> 
    </executor> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <invoker> 
     <invoker.1/> 
     <invoker.2/> 
     <invoker.3/> 
    </invoker> 
    <recipient> 
     <recipient.1/> 
     <recipient.2/> 
     <recipient.3/> 
    </recipient> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
</testExecution> 

产生想要的,正确的结果

<testExecution> 
    <test> 
     <test.1/> 
     <test.2/> 
     <test.3/> 
    </test> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <people> 
     <importantPeople> 
     <executor> 
      <executor.1/> 
      <executor.2/> 
      <executor.3/> 
     </executor> 
     <comment> 
      <comment.1/> 
      <comment.2/> 
      <comment.3/> 
     </comment> 
     <comment> 
      <comment.1/> 
      <comment.2/> 
      <comment.3/> 
     </comment> 
     </importantPeople> 
     <invoker> 
     <invoker.1/> 
     <invoker.2/> 
     <invoker.3/> 
     </invoker> 
    </people> 
    <recipient> 
     <recipient.1/> 
     <recipient.2/> 
     <recipient.3/> 
    </recipient> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
    <comment> 
     <comment.1/> 
     <comment.2/> 
     <comment.3/> 
    </comment> 
</testExecution>