2010-11-25 49 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>