当前位置: 首页 > 知识库问答 >
问题:

使非逻辑平面结构分层

籍永安
2023-03-14

我想按标题分组,但当结构不符合逻辑时,分区就会停止。例如

输入:


    <?xml version="1.0" encoding="UTF-8"?>
    <document id="21" state="Schrijven" documentTypeName="News">
            <document track-changes="false" version="1">
            <section>
                    <h1>Title h1</h1>
                        <p>Some text</p>
                        <p/>
                    <h2>Title h2</h2>
                       <p>Some text</p>
                       <p/>
                    <h3>Title h3</h3>
                       <p>Some text</p>
                       <p/>
                    <h2>Title h2</h2>
                       <p>Some text</p>
                       <p/>
                    <h4>Title h4</h4>
                       <p>Some text</p>
                       <p/>   
            </section>        
            </document>
        </document>

输出


    <html>
       <head>
          <meta charset="UTF-8"/>
        </head>
       <body data-sws-documentkey="id-00021">
          <section class="level-newsitem">
             <h1 class="nieuws">Title h1</h1>
             <p>Some text</p>
             <p/>
             <section class="level">
                <h2>Title h2</h2>
                <p>Some text</p>
                <p/>
                <section class="level">
                   <h3>Title h3</h3>
                   <p>Some text</p>
                   <p/>
                </section>
             </section>
             <section class="level">
                <h2>Title h2</h2>
                <p>Some text</p>
                <p/>
                <h4>Title h4</h4>
                <p>Some text</p>
                <p/>
             </section>
          </section>
       </body>
    </html>

期望输出


    <html>
       <head>
          <meta charset="UTF-8"/>
        </head>
       <body data-sws-documentkey="id-00021">
          <section class="level-newsitem">
             <h1 class="nieuws">Title h1</h1>
             <p>Some text</p>
             <p/>
             <section class="level">
                <h2>Title h2</h2>
                <p>Some text</p>
                <p/>
                <section class="level">
                   <h3>Title h3</h3>
                   <p>Some text</p>
                   <p/>
                </section>
             </section>
             <section class="level">
                <h2>Title h2</h2>
                <p>Some text</p>
                <p/>
                <section class="level">
                   <h4>Title h4</h4>
                   <p>Some text</p>
                   <p/>
                </section>
             </section>
          </section>
       </body>
    </html>

样式表


    <?xml version="1.0" encoding="UTF-8"?>

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:cwc="urn:cwc"
        xmlns:p1="urn:p1"
        exclude-result-prefixes="xs cwc p1"
        version="2.0">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>
    <xsl:strip-space elements="document meta section div row"/>

    <xsl:variable name="DocumentKey">
        <xsl:value-of select="concat('id-000', /document[1]/@id)"/>
    </xsl:variable>

    <xsl:variable name="DocSoort">
        <xsl:value-of select="/document/@documentTypeName"/>
    </xsl:variable>

    <xsl:template match="document">
        <html>
            <head> 
                <meta charset="UTF-8"/>
                <xsl:if test="./meta/description">
                    <meta name="description">
                    <xsl:attribute name="content">
                        <xsl:value-of select="./meta/description"/>
                    </xsl:attribute>
                    </meta>
                </xsl:if>    
                <title><xsl:value-of select="./naam"/></title>
             </head>
            <body data-sws-documentkey="{$DocumentKey}">
                <xsl:choose>
                    <xsl:when test="$DocSoort='Note'">
                        <xsl:apply-templates mode="Note"/>
                    </xsl:when>
                    <xsl:when test="$DocSoort='News'">
                        <xsl:apply-templates mode="News"/></xsl:when>
                </xsl:choose>
             </body>    
        </html>
    </xsl:template>

    <xsl:template match="h1" mode="#all">
    <xsl:variable name="DocSoorttitel">
        <xsl:choose>
            <xsl:when test="$DocSoort='Note'">noteitem</xsl:when>
            <xsl:when test="$DocSoort='News'">newsitem</xsl:when>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="count">
        <xsl:value-of select="count(preceding::h1)"/>
    </xsl:variable>
        <xsl:choose>
            <xsl:when test="$count = 0">
                <xsl:copy>
                    <xsl:attribute name="class">
                        <xsl:value-of select="$DocSoorttitel"/>
                    </xsl:attribute>
                    <xsl:apply-templates select="@*[name()!='class']" mode="#current"/>
                    <xsl:apply-templates mode="#current"/>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="@*" mode="#current"/>
                    <xsl:apply-templates mode="#current"/>
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="naam|meta|lastmodified" mode="#all"/>

    <xsl:template match="*/document" mode="#all">
        <xsl:choose>
            <xsl:when test="not(./section)">
                <section>
                    <xsl:attribute name="class">
                        <xsl:value-of select="lower-case(concat('sws-', $DocSoort))"/>
                    </xsl:attribute>
                      <xsl:call-template name="groupingheaders"/>
                </section>    
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates mode="#current"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="section" mode="#all">
        <section>
            <xsl:attribute name="class">
                <xsl:value-of select="lower-case(concat('level-', $DocSoort))"/>
            </xsl:attribute>
            <xsl:call-template name="groupingheaders"/>
        </section>
    </xsl:template>

    <xsl:template name="groupingheaders">
        <xsl:choose>
            <xsl:when test="$DocSoort='Note'">
                <xsl:for-each-group select="*" group-starting-with="div[@class = 'letop'][parent::document or parent::section]|h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <xsl:choose>
                        <xsl:when test="current-group()[1]/self::div[@class = 'letop'][parent::document or parent::section]|current-group()[1]/self::h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                            <section class="level">
                                <xsl:call-template name="group2"/>
                            </section>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()" mode="#current"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:when>
            <xsl:when test="$DocSoort='News'">
                <xsl:for-each-group select="*" group-starting-with="h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <xsl:choose>
                        <xsl:when test="current-group()[1]/self::h2[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                            <section class="level">
                                <xsl:call-template name="group2"/>
                            </section>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="current-group()" mode="#current"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each-group>
            </xsl:when>
        </xsl:choose>
    </xsl:template>

    <xsl:template name="group2">
        <xsl:for-each-group select="current-group()" group-starting-with="h3[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
            <xsl:choose>
                <xsl:when test="current-group()[1]/self::h3[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <section class="level">
                        <xsl:call-template name="group3"/>
                    </section>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()" mode="#current"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template name="group3">
        <xsl:for-each-group select="current-group()" group-starting-with="h4[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
            <xsl:choose>
                <xsl:when test="current-group()[1]/self::h4[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <section class="level">
                        <xsl:call-template name="group4"/>
                    </section>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()" mode="#current"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template name="group4">
        <xsl:for-each-group select="current-group()" group-starting-with="h5[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
            <xsl:choose>
                <xsl:when test="current-group()[1]/self::h5[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <section class="level">
                        <xsl:call-template name="group5"/>
                    </section>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()" mode="#current"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template name="group5">
        <xsl:for-each-group select="current-group()" group-starting-with="h6[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
            <xsl:choose>
                <xsl:when test="current-group()[1]/self::h6[parent::document or parent::section][count(text()[normalize-space()]) > 0]">
                    <section class="level">
                        <xsl:apply-templates select="current-group()" mode="#current"/>
                    </section>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()" mode="#current"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:template>

    <xsl:template match="node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>


    </xsl:stylesheet>

共有1个答案

梁渊
2023-03-14

可以使用递归函数进行常规分组:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="2.0">

    <xsl:output method="html" indent="yes"/>

    <xsl:param name="prefix" as="xs:string" select="'h'"/>
    <xsl:param name="max-level" as="xs:integer" select="6"/>

    <xsl:function name="mf:group" as="node()*">
        <xsl:param name="nodes" as="node()*"/>
        <xsl:param name="level" as="xs:integer"/>
        <xsl:for-each-group select="$nodes" group-starting-with="*[local-name() eq concat($prefix, $level)]">
            <xsl:choose>
                <xsl:when test="self::*[local-name() eq concat($prefix, $level)]">
                    <section class="level">
                        <xsl:apply-templates select="."/>
                        <xsl:sequence select="mf:group(current-group() except ., $level + 1)"/>
                    </section>
                </xsl:when>
                <xsl:when test="$level lt $max-level">
                    <xsl:sequence select="mf:group(current-group(), $level + 1)"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:apply-templates select="current-group()"/>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:function>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* , node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*[h1 | h2 | h3 | h4 | h5 | h6]">
        <xsl:copy>
            <xsl:sequence select="mf:group(*, 1)"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

这改变了

<document id="21" state="Schrijven" documentTypeName="News">
    <document track-changes="false" version="1">
        <section>
            <h1>Title h1</h1>
            <p>Some text</p>
            <p/>
            <h2>Title h2</h2>
            <p>Some text</p>
            <p/>
            <h3>Title h3</h3>
            <p>Some text</p>
            <p/>
            <h2>Title h2</h2>
            <p>Some text</p>
            <p/>
            <h4>Title h4</h4>
            <p>Some text</p>
            <p/>   
        </section>        
    </document>
</document>

<document id="21" state="Schrijven" documentTypeName="News">

   <document track-changes="false" version="1">

      <section>
         <section class="level">
            <h1>Title h1</h1>
            <p>Some text</p>
            <p></p>
            <section class="level">
               <h2>Title h2</h2>
               <p>Some text</p>
               <p></p>
               <section class="level">
                  <h3>Title h3</h3>
                  <p>Some text</p>
                  <p></p>
               </section>
            </section>
            <section class="level">
               <h2>Title h2</h2>
               <p>Some text</p>
               <p></p>
               <section class="level">
                  <h4>Title h4</h4>
                  <p>Some text</p>
                  <p></p>
               </section>
            </section>
         </section>
      </section>        

   </document>

</document>

您需要为其他元素添加模板,如果第一级需要特殊处理,可以使用一些条件检查扩展函数,或者为第一级编写模板或函数

 类似资料:
  • 本文向大家介绍oracle逻辑结构分析,包括了oracle逻辑结构分析的使用技巧和注意事项,需要的朋友参考一下 oracle的逻辑结构包括表空间(tablespace),段(segment),区(extent),数据块(data block) oracle数据库在逻辑上是由多个表间组成的,表空间中存储的对象叫段,比如数据段,索引段,和回退段。段由区组成,区是磁盘分配的最小单位。段的增大是通过增加区

  • 本文向大家介绍.NET逻辑分层架构总结,包括了.NET逻辑分层架构总结的使用技巧和注意事项,需要的朋友参考一下 一.基础知识准备:   1.层的原则:   (1)每一层以接口方式供上层调用。   (2)上层只能调用下层。   (3)依赖分为松散交互和严格交互两种。   2.业务逻辑分类:   (1)应用逻辑。   (2)领域逻辑。   3.采用的层:   (1)表示层(用户接口层):领域无关。  

  • 每条链有独立的数据存储文件 每个智能合约都独立的数据存储空间 每个智能合约可以创建多个数据表

  • 语句和逻辑结构 #include <stdio.h> #include <stdlib.h> #include <Windows.h> //01.杂乱知识点: // 1.内存分配函数malloc(); // (1).分配单位:字节 // (2).分配方式: // 鲸吞+慢咽 // 2.内存分配注意事项: // 32位的单个进程一口气对多开辟2G

  • 本文向大家介绍浅析.NET逻辑分层架构,包括了浅析.NET逻辑分层架构的使用技巧和注意事项,需要的朋友参考一下 一.基础知识准备:   1.层的原则:   (1)每一层以接口方式供上层调用。   (2)上层只能调用下层。   (3)依赖分为松散交互和严格交互两种。   2.业务逻辑分类:   (1)应用逻辑。   (2)领域逻辑。   3.采用的层:   (1)表示层(用户接口层):领域无关。  

  • 本文向大家介绍JavaScript 逻辑非运算符(!),包括了JavaScript 逻辑非运算符(!)的使用技巧和注意事项,需要的朋友参考一下 示例 逻辑NOT(!)运算符对表达式执行逻辑取反。 语法: 返回值: 一个Boolean。 描述 逻辑NOT(!)运算符对表达式执行逻辑取反。 布尔值只需取反即可:!true === false和!false === true。 非布尔值首先转换为布尔值,