1

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

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>

输入:

    <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>

谢谢!

4

2 回答 2

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 存在的主要理由。(祝贺马丁的第一篇文章并正确使用了它。)
  4. 您的示例输入中缺少尖括号。
  5. 我认为这subscection_total_pages应该拼写为 subsection_total_pages,对于scection_total_pages.

有趣的替代解决方案

与其将处理module分为两种情况,不如发明一个对 all 有效的键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 属性的模块组合在一起。

于 2012-10-16T14:42:00.743 回答
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>

这似乎有正确的总数。显然我没有要拉入这些文件,所以内容都丢失了。

于 2012-10-16T14:27:27.147 回答