我怎样才能使用键来改变它

时间:2010-11-25 23:08:18

标签: xml xslt xslt-1.0

我可以在不使用键的情况下编写一个非常糟糕的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>

2 个答案:

答案 0 :(得分: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>

注意:细粒度遍历。 “仅适用于此测试”的关键字如下。用于“关闭此级别”的空模板。推送方式“保持处理”。它可以是完全的“拉式”匹配“标记之前的流行”。

答案 1 :(得分:1)

此转换使用并覆盖标识规则。使用executor函数检索key()后面的注释。紧接executor之后的invokercommentexecutor将被复制到名为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>