XSLT如何在Muenchian分组变换中增加?

时间:2012-10-16 12:19:23

标签: xslt xslt-1.0

我有一个分组变换,我想在其中包含计数/增量。如果分配了分组,变换分组值。值是变换用于连接在一起的文件位置,因此内容作为一个输出。如果没有分配分组,则转换使用值来获取文件内容,而不将其附加到任何内容。

XSLT:

   <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
       <xsl:output method="xml" indent="yes"/>
       <xsl:key name="modules" match="module[@group]" use="concat(generate-id(..), '|', @group)"/>

       <xsl:template match="root">
           <AllSections>
               <xsl:apply-templates />
           </AllSections>
       </xsl:template>

       <!-- NON GROUPED PART -->
       <xsl:template match="module[not(@group)]">
              <page>
               <content>
                <xsl:variable name="var">
                 <xsl:value-of select="comp"/>
                </xsl:variable>
                <xsl:copy-of select="document(concat('../myfile/', string($var)))"/>
               </content>
             </page>
       </xsl:template>

       <!--GROUPED PART -->
       <xsl:template match="module[@group][generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])]">
           <xsl:variable name="modules" select="key('modules', concat(generate-id(..), '|', @group))"/>
           <page>
               <content>
                <xsl:for-each select="$modules/comp">
                 <xsl:copy-of select="document(concat('../myfile/', .))"/>
                </xsl:for-each>
               </content>

           </page>
       </xsl:template>

       <xsl:template match="module"/>

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

INPUT:

    <root>
        <section>
            <subsection>
                <module>
                    <comp>aaa.html</comp>
                </module>
                <module group='group01'>
                    <comp>bbb.html</comp>
                </module>
                <module group='group01'>
                    <comp>ccc.html</comp>
                </module>
                <module>
                    <comp>ddd.html</comp>
                </module>
                <module>
                    <comp>eee.html</comp>
                </module>
            </subsection>
        </section>
        <section>
            <subsection>
                <module group ="group02">
                    <comp>fff.html</comp>
                </module>
                <module group ="group02">
                    <comp>ggg.html</comp>
                </module>
                <module>
                    <comp>hhh.html</comp>
                </module>
                <module group ="group03">
                    <comp>iii.html</comp>
                </module>
                <module group ="group03">
                    <comp>jjj.html</comp>
                </module>
            </subsection>
            <subsection>
                <module group ="group04">
                    <comp>kkk.html</comp>
                </module>
                <module group ="group04">
                    <comp>lll.html</comp>
                </module>
                <module group ="group05">
                    <comp>mmm.html</comp>
                </module>
                <module group ="group05">
                    <comp>nnn.html</comp>
                </module>
                <module group ="group06">
                    <comp>ooo.html</comp>
                </module>
                <module group ="group06">
                    <comp>ppp.html/comp>
                </module>
                <module>
                    <comp>qqq.html</comp>
                </module>
            </subsection>
        </section>
    </root>

输出样本:

    <?xml version="1.0" encoding="utf-8"?>
    <AllSections>   
        <section>        
            <subsection>            
                <page>
                    <content>
                        CONTENT FROM aaa.html
                    </content>
                </page>            
                <page>
                    <content>
                        CONTENT FROM bbb.html
                        CONTENT FROM ccc.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM ddd.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM eee.html
                    </content>
                </page>            
            </subsection>       
        </section>    
        <section>       
            <subsection>  
                <page>
                    <content>
                        CONTENT FROM fff.html
                        CONTENT FROM ggg.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM hhh.html
                    </content>
                </page>            
                <page>
                    <content>
                        CONTENT FROM iii.html
                        CONTENT FROM jjj.html
                    </content>
                </page>         
            </subsection>        
            <subsection>            
                <page>
                    <content>
                        CONTENT FROM kkk.html
                        CONTENT FROM lll.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM mmm.html
                        CONTENT FROM nnn.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM ooo.html
                        CONTENT FROM ppp.html
                    </content>
                </page>           
                <page>
                    <content>
                        CONTENT FROM qqq.html
                    </content>
                </page>           
            </subsection>       
        </section>    
    </AllSections>

我正在尝试做的是为总页面设置一个计数器,见下文,关于部分和子部分并指定增量。我试过param但它需要一个递归模板?如果我放入sem来打破其余的转换。使用模板时是否没有创建“循环”?

输出尝试获取:

   <AllSections>   
        <section>        
            <subsection>            
                <page>
                    <content>
                        CONTENT FROM aaa.html
                    </content>
                    <page_no>1</page_no>
                </page>            
                <page>
                    <content>
                        CONTENT FROM bbb.html
                        CONTENT FROM ccc.html
                    </content>
                    <page_no>2</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM ddd.html
                    </content>
                    <page_no>3</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM eee.html
                    </content>
                    <page_no>4</page_no>
                </page>                   
                <subscection_total_pages>4</subscection_total_pages>
            </subsection>  
            <scection_total_pages>4</scection_total_pages>
        </section>    
        <section>       
            <subsection>  
                <page>
                    <content>
                        CONTENT FROM fff.html
                        CONTENT FROM ggg.html
                    </content>
                    <page_no>1</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM hhh.html
                    </content>
                    <page_no>2</page_no>
                </page>            
                <page>
                    <content>
                        CONTENT FROM iii.html
                        CONTENT FROM jjj.html
                    </content>
                    <page_no>3</page_no>
                </page>
                <subscection_total_pages>3</subscection_total_pages>
            </subsection>        
            <subsection>            
                <page>
                    <content>
                        CONTENT FROM kkk.html
                        CONTENT FROM lll.html
                    </content>
                    <page_no>1</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM mmm.html
                        CONTENT FROM nnn.html
                    </content>
                    <page_no>2</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM ooo.html
                        CONTENT FROM ppp.html
                    </content>
                    <page_no>3</page_no>
                </page>           
                <page>
                    <content>
                        CONTENT FROM qqq.html
                    </content>
                    <page_no>4</page_no>
                </page>
                <subscection_total_pages>4</subscection_total_pages>
            </subsection>
            <scection_total_pages>7</scection_total_pages>
        </section>    
    </AllSections>

谢谢!

2 个答案:

答案 0 :(得分:0)

这是我的建议:

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

       <xsl:key name="modules" match="module[@group]" use="concat(generate-id(..), '|', @group)"/>

       <xsl:template match="root">
           <AllSections>
               <xsl:apply-templates />
           </AllSections>
       </xsl:template>

       <xsl:template match="section">
         <xsl:copy>
           <xsl:apply-templates select="subsection"/>
           <section_total_pages>
             <xsl:value-of select="
             count(subsection/module[not(@group)]) + 
             count(subsection/module[@group][generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])])"/>
           </section_total_pages>
         </xsl:copy>
       </xsl:template>

       <xsl:template match="subsection">
          <xsl:copy>
            <xsl:variable name="groups" select="module[not(@group)] | module[@group][generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])]"/>
            <xsl:apply-templates select="$groups"/>
            <subsection_total_pages>
              <xsl:value-of select="count($groups)"/>
            </subsection_total_pages>
          </xsl:copy>
        </xsl:template>


       <!-- NON GROUPED PART -->
       <xsl:template match="module[not(@group)]">
              <page>
               <content>
                <xsl:copy-of select="document(concat('../myfile/', comp))"/>
               </content>
               <xsl:apply-templates select="." mode="page-no"/>
             </page>
       </xsl:template>

       <!--GROUPED PART -->
       <xsl:template match="module[@group]">
           <xsl:variable name="modules" select="key('modules', concat(generate-id(..), '|', @group))"/>
           <page>
               <content>
                <xsl:for-each select="$modules/comp">
                  <xsl:copy-of select="document(concat('../myfile/', .))"/>
                </xsl:for-each>
               </content>
               <xsl:apply-templates select="." mode="page-no"/>
           </page>
       </xsl:template>

       <xsl:template match="module" mode="page-no">
               <page_no>
                 <xsl:number count="module[not(@group)] | module[@group][generate-id() = generate-id(key('modules', concat(generate-id(..), '|', @group))[1])]"/>
               </page_no>
       </xsl:template>


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

当我将以上代码与Saxon 6.5.5一起应用于输入

<root>
    <section>
        <subsection>
            <module>
                <comp>aaa.html</comp>
            </module>
            <module group='group01'>
                <comp>bbb.html</comp>
            </module>
            <module group='group01'>
                <comp>ccc.html</comp>
            </module>
            <module>
                <comp>ddd.html</comp>
            </module>
            <module>
                <comp>eee.html</comp>
            </module>
        </subsection>
    </section>
    <section>
        <subsection>
            <module group ="group02">
                <comp>fff.html</comp>
            </module>
            <module group ="group02">
                <comp>ggg.html</comp>
            </module>
            <module>
                <comp>hhh.html</comp>
            </module>
            <module group ="group03">
                <comp>iii.html</comp>
            </module>
            <module group ="group03">
                <comp>jjj.html</comp>
            </module>
        </subsection>
        <subsection>
            <module group ="group04">
                <comp>kkk.html</comp>
            </module>
            <module group ="group04">
                <comp>lll.html</comp>
            </module>
            <module group ="group05">
                <comp>mmm.html</comp>
            </module>
            <module group ="group05">
                <comp>nnn.html</comp>
            </module>
            <module group ="group06">
                <comp>ooo.html</comp>
            </module>
            <module group ="group06">
                <comp>ppp.html</comp>
            </module>
            <module>
                <comp>qqq.html</comp>
            </module>
        </subsection>
    </section>
</root>

我得到了结果

<AllSections>
   <section>
      <subsection>
         <page>
            <content/>
            <page_no>1</page_no>
         </page>
         <page>
            <content/>
            <page_no>2</page_no>
         </page>
         <page>
            <content/>
            <page_no>3</page_no>
         </page>
         <page>
            <content/>
            <page_no>4</page_no>
         </page>
         <subsection_total_pages>4</subsection_total_pages>
      </subsection>
      <section_total_pages>4</section_total_pages>
   </section>
   <section>
      <subsection>
         <page>
            <content/>
            <page_no>1</page_no>
         </page>
         <page>
            <content/>
            <page_no>2</page_no>
         </page>
         <page>
            <content/>
            <page_no>3</page_no>
         </page>
         <subsection_total_pages>3</subsection_total_pages>
      </subsection>
      <subsection>
         <page>
            <content/>
            <page_no>1</page_no>
         </page>
         <page>
            <content/>
            <page_no>2</page_no>
         </page>
         <page>
            <content/>
            <page_no>3</page_no>
         </page>
         <page>
            <content/>
            <page_no>4</page_no>
         </page>
         <subsection_total_pages>4</subsection_total_pages>
      </subsection>
      <section_total_pages>7</section_total_pages>
   </section>
</AllSections>

似乎总数正确。显然我没有提供这些文件,因此内容全部丢失。

答案 1 :(得分:0)

此XSLT 1.0样式表......

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

<xsl:key name="kModules" match="module[@group]" use="concat(generate-id(..), '|', @group)"/>

<xsl:template match="/*">
  <AllSections>
    <xsl:apply-templates />
  </AllSections>
</xsl:template>

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

<xsl:template match="section">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
    <section_total_pages><xsl:number
       value="count(subsection/module[ not(@group) or 
  (generate-id()=generate-id( key('kModules',concat(generate-id(..),'|',@group))[1]))])"/>
    </section_total_pages> 
  </xsl:copy>
</xsl:template>

<xsl:template match="subsection">
  <xsl:variable name="subsect-id" select="concat(generate-id(),'|')" />
  <xsl:copy>
    <xsl:variable name="page-heads"
    select="module[ not(@group) or 
            (generate-id()=generate-id( key('kModules',concat($subsect-id, @group))[1]))]"/>
    <xsl:apply-templates select="
      @*| node()[not(self::module)] | $page-heads"/>
    <subsection_total_pages><xsl:number value="count($page-heads)"/></subsection_total_pages>
  </xsl:copy>
</xsl:template>  

<xsl:template match="module">
  <xsl:variable name="subsect-id" select="concat(generate-id(..),'|')" />
  <page>
   <content>
     <xsl:apply-templates select="key('kModules',concat($subsect-id, @group))/comp | comp" />
   </content>
   <page_no><xsl:number count="module[not(@group) or 
     (generate-id() =
      generate-id( key('kModules',concat($subsect-id, @group))[1]))]"/></page_no>  
  </page>
</xsl:template>

<xsl:template match="comp">
  <!-- Change this sequence constructor to do your document pulling bit. -->
  <xsl:comment>content from <xsl:value-of select="." /></xsl:comment>
</xsl:template>

</xsl:stylesheet>

...当应用于给定的样本输入时,产生...

<AllSections>
  <section>
    <subsection>
      <page>
        <content>
          <!--content from aaa.html-->
        </content>
        <page_no>1</page_no>
      </page>
      <page>
        <content>
          <!--content from bbb.html-->
          <!--content from ccc.html-->
        </content>
        <page_no>2</page_no>
      </page>
      <page>
        <content>
          <!--content from ddd.html-->
        </content>
        <page_no>3</page_no>
      </page>
      <page>
        <content>
          <!--content from eee.html-->
        </content>
        <page_no>4</page_no>
      </page>
      <subsection_total_pages>4</subsection_total_pages>
    </subsection>
    <section_total_pages>4</section_total_pages>
  </section>
  <section>
    <subsection>
      <page>
        <content>
          <!--content from fff.html-->
          <!--content from ggg.html-->
        </content>
        <page_no>1</page_no>
      </page>
      <page>
        <content>
          <!--content from hhh.html-->
        </content>
        <page_no>2</page_no>
      </page>
      <page>
        <content>
          <!--content from iii.html-->
          <!--content from jjj.html-->
        </content>
        <page_no>3</page_no>
      </page>
      <subsection_total_pages>3</subsection_total_pages>
    </subsection>
    <subsection>
      <page>
        <content>
          <!--content from kkk.html-->
          <!--content from lll.html-->
        </content>
        <page_no>1</page_no>
      </page>
      <page>
        <content>
          <!--content from mmm.html-->
          <!--content from nnn.html-->
        </content>
        <page_no>2</page_no>
      </page>
      <page>
        <content>
          <!--content from ooo.html-->
          <!--content from ppp.html-->
        </content>
        <page_no>3</page_no>
      </page>
      <page>
        <content>
          <!--content from qqq.html-->
        </content>
        <page_no>4</page_no>
      </page>
      <subsection_total_pages>4</subsection_total_pages>
    </subsection>
    <section_total_pages>7</section_total_pages>
  </section>
</AllSections>

备注

  1. 模板匹配comp与测试目的一样。出于生产目的,使用document()函数按需更改。
  2. 我会避免在匹配条件下进行Muenchian测试。由于经常测试模板匹配测试,这将非常痛苦。
  3. 您的问题的结点由xsl:number count属性解决。这是xsl:number的主要存在理由。 (祝贺Martin第一篇文章并正确使用它。)
  4. 示例输入中缺少一个尖括号。
  5. 我认为subscection_total_pages拼写为subsection_total_pages,而scection_total_pages则类似。
  6. 有趣的替代解决方案

    不是将module的处理分为两种情况,而是可以创建一个对所有modules有效的密钥,其中,如果group属性不存在,则键值为一个独一无二的。采用这种方法的以下替代解决方案假定generate-id()函数永远不会包含双@字符。

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*" />  
    
    <xsl:key name="kModules" match="module" use="
      concat(generate-id(..),'|',
      substring-before( concat( generate-id(),'@',@group,'@',generate-id()), '@@' ),
      @group)"/>
    
    <xsl:template match="/*">
      <AllSections>
        <xsl:apply-templates />
      </AllSections>
    </xsl:template>
    
    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="section">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <section_total_pages><xsl:number
           value="count(subsection/module[  
      (generate-id()=generate-id( key('kModules',
            concat(generate-id(..),'|',
      substring-before( concat( generate-id(),'@',@group,'@',generate-id()), '@@' ),
      @group))[1]))])"/>
        </section_total_pages> 
      </xsl:copy>
    </xsl:template>
    
    <xsl:template match="subsection">
      <xsl:variable name="subsect-id" select="concat(generate-id(),'|')" />
      <xsl:copy>
        <xsl:variable name="page-heads"
        select="module[ 
                (generate-id()=generate-id( key('kModules',concat(generate-id(..),'|',
      substring-before( concat( generate-id(),'@',@group,'@',generate-id()), '@@' ),@group))[1]))]"/>
        <xsl:apply-templates select="@*| node()[not(self::module)] | $page-heads"/>
        <subsection_total_pages><xsl:number value="count($page-heads)"/></subsection_total_pages>
      </xsl:copy>
    </xsl:template>  
    
    <xsl:template match="module">
      <xsl:variable name="subsect-id" select="concat(generate-id(..),'|')" />
      <page>
       <content>
         <xsl:apply-templates select="key('kModules',concat(generate-id(..),'|',
      substring-before( concat( generate-id(),'@',@group,'@',generate-id()), '@@' ),
      @group))/comp" />
       </content>
       <page_no><xsl:number count="module[
         (generate-id()=generate-id( key('kModules',concat(generate-id(..),'|',
      substring-before( concat( generate-id(),'@',@group,'@',generate-id()), '@@' ),
      @group))[1]))]"/></page_no>  
      </page>
    </xsl:template>
    
    <xsl:template match="comp">
      <!-- Change this sequence constructor to do your document pulling bit. -->
      <xsl:comment>content from <xsl:value-of select="." /></xsl:comment>
    </xsl:template>
    
    </xsl:stylesheet>
    

    替代解决方案如何运作?

    考虑键value

    中使用的Xpath表达式的重要部分
    concat(
      substring-before(
        concat( generate-id(), '@' ,@group, '@', generate-id()),
        '@@' ),
      @group
      )
    

    如果@group不存在或为空,则相当于......

    concat(
      substring-before(
        concat( generate-id(), '@@', generate-id()),
        '@@' ),
      @group
      )
    

    ......或......

    concat( generate-id(), @group)
    

    ......或......

    generate-id()
    

    ...这对每个节点都是唯一的,这就是我们想要的。

    但如果@group不为空,那么这相当于......

    concat(
      '',
      @group
      )
    

    ......或......

    @group
    

    允许将具有group属性的模块组合在一起。