代码之家  ›  专栏  ›  技术社区  ›  sanjay

XSLT-XML到HTML trasform-从一个级别元素创建嵌套的<div>

  •  0
  • sanjay  · 技术社区  · 6 年前

    <doc>
        <para>111111111111</para>
        <!--start div1-->
        <para>2222222</para>
        <para>3333333</para>
        <!--start div2-->
        <para>4444444</para>
        <para>5555555</para>
        <para>6666666</para>
        <!--start div3-->
        <para>7777777</para>
        <para>8888888</para>
        <!--end div3-->
        <para>9999999</para>
        <para>1010110</para>
        <!--end div2-->
        <para>11,11,11</para>
        <para>12,12,12,</para>
        <!--end div1-->
        <para>13,13,13</para>
    </doc>
    

    我正在对这个输入进行XSLT转换,我需要将这些元素放在嵌套的 <div> 元素。从上一阶段添加注释,以确定 < 元素应该消失。在给定的示例中,有三个嵌套 div 元素在那里,但它可以改变。我的预期产量是,

    <doc>
        <para>111111111111</para>
        <div>
            <!--start div1-->
            <para>2222222</para>
            <para>3333333</para>
            <div>
                <!--start div2-->
                <para>4444444</para>
                <para>5555555</para>
                <para>6666666</para>
                <div>
                    <!--start div3-->
                    <para>7777777</para>
                    <para>8888888</para>
                    <!--end div3-->
                </div>
                <para>9999999</para>
                <para>1010110</para>
                <!--end div2-->
            </div>
            <para>11,11,11</para>
            <para>12,12,12,</para>
            <!--end div1-->
        </div>
        <para>13,13,13</para>
    </doc>
    

    我不能写三个嵌套的 <for-each> 按嵌套方式分组 <分区> 元素可以在其他输入中变化。(可以转到嵌套的第四层或第五层等)。

    我试过跟在后面,但它只是先加上 <分区>

    <xsl:template match="doc">
            <doc>
                <xsl:for-each-group select="*|comment()" group-adjacent="
                    if (self::comment())
                    then
                    substring-after(self::comment(),' ')
                    else
                    local-name()">
    
                    <xsl:for-each-group select="current-group()" group-starting-with="*">
                        <div id="{local-name()}-{position()}">   
                            <xsl:copy-of select="current-group()" />      
                        </div>    
                    </xsl:for-each-group>  
    
                </xsl:for-each-group>
            </doc>
    
        </xsl:template>
    

    有人能给我建议一个实现这些嵌套的方法吗 <分区> <对于每个> 在XSLT中?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Martin Honnen    6 年前

    您可以在模板或函数中实现递归,下面是一个函数,因为它允许更紧凑的语法:

      <xsl:function name="mf:group" as="node()*">
          <xsl:param name="input" as="node()*"/>
          <xsl:param name="level" as="xs:integer"/>
          <xsl:for-each-group select="$input" group-starting-with="comment()[. = 'start div' || $level]">
              <xsl:choose>
                  <xsl:when test="self::comment()[. = 'start div' || $level]">
                      <xsl:for-each-group select="current-group()" group-ending-with="comment()[. = 'end div' || $level]">
                          <xsl:choose>
                              <xsl:when test="current-group()[last()][self::comment()[. = 'end div' || $level]]">
                                  <div>
                                      <xsl:apply-templates select="."/>
                                      <xsl:sequence select="mf:group(current-group()[not(position() = (1, last()))], $level + 1)"/>
                                      <xsl:apply-templates select="current-group()[last()]"/>
                                  </div>                              
                              </xsl:when>
                              <xsl:otherwise>
                                  <xsl:sequence select="current-group()"/>
                              </xsl:otherwise>
                          </xsl:choose>
                      </xsl:for-each-group>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:function>
    

    || concat 电话):

    <?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="3.0">
    
      <xsl:function name="mf:group" as="node()*">
          <xsl:param name="input" as="node()*"/>
          <xsl:param name="level" as="xs:integer"/>
          <xsl:for-each-group select="$input" group-starting-with="comment()[. = 'start div' || $level]">
              <xsl:choose>
                  <xsl:when test="self::comment()[. = 'start div' || $level]">
                      <xsl:for-each-group select="current-group()" group-ending-with="comment()[. = 'end div' || $level]">
                          <xsl:choose>
                              <xsl:when test="current-group()[last()][self::comment()[. = 'end div' || $level]]">
                                  <div>
                                      <xsl:apply-templates select="."/>
                                      <xsl:sequence select="mf:group(current-group()[not(position() = (1, last()))], $level + 1)"/>
                                      <xsl:apply-templates select="current-group()[last()]"/>
                                  </div>                              
                              </xsl:when>
                              <xsl:otherwise>
                                  <xsl:sequence select="current-group()"/>
                              </xsl:otherwise>
                          </xsl:choose>
                      </xsl:for-each-group>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:function>
    
      <xsl:output indent="yes"/>
    
      <xsl:mode on-no-match="shallow-copy"/>
    
      <xsl:template match="doc">
          <xsl:copy>
              <xsl:sequence select="mf:group(node(), 1)"/>
          </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/94hvTzt

        2
  •  0
  •   imran    6 年前
    <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="comment()[.='start div1' or .='start div2' or .='start div3' or .='end div3' or  .='end div2' or .='end div1']">
            <xsl:choose>
                <xsl:when test=". ='start div1'">
                    <xsl:text disable-output-escaping="yes">&lt;div&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;!--start div1--&gt;</xsl:text>
                </xsl:when>
                <xsl:when test=". ='start div2'">
                    <xsl:text disable-output-escaping="yes">&lt;div&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;!--start div2--&gt;</xsl:text>
                </xsl:when>
                <xsl:when test=". ='start div3'">
                    <xsl:text disable-output-escaping="yes">&lt;div&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;!--start div3--&gt;</xsl:text>
                </xsl:when>
                <xsl:when test=". ='end div3'">
                    <xsl:text disable-output-escaping="yes">&lt;!--end div3--&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>
                </xsl:when>
                <xsl:when test=". ='end div2'">
                    <xsl:text disable-output-escaping="yes">&lt;!--end div2--&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>
                </xsl:when>
                <xsl:when test=". ='end div1'">
                    <xsl:text disable-output-escaping="yes">&lt;!--end div1--&gt;</xsl:text>
                    <xsl:text disable-output-escaping="yes">&lt;/div&gt;</xsl:text>
                </xsl:when>
            </xsl:choose>
        </xsl:template>
    You may try like this