开发者

Positional grouping: xslt conversion of html

I have the following html file and i want to run a transformation so that all the h1,h2,h3 tags will converted into corresponding divs. h2 will always be a nested div of h1 and if there are 2 h2 tags then it should have there own divs. same way h3 will always be a nested div of h2.

<body>
   <p> this is a text</p>
   <a href="http://yahoo.com">click here</a>
   <h3>this is heading 3</h3>
   <p>text for heading 3</p>
    <h1>
      heading 1
   </h1>
     this is a text for heading 1
     <a href="link"> 开发者_StackOverflow中文版This is a link </a>
  <h2>
       this is heading 2

  </h2>
          this is a text for heading 2
  <h2>
          this is heading 2 again
  </h2>
         this is a text for heading 2 again
  </body>

" The output of above should be like :

<body>
   <p> this is a text</p>
   <a href="http://yahoo.com">click here</a>
   <div>
    <heading>this is heading 3</heading>
   <p>text for heading 3</p>
    <div>

 <div>
  <heading>
    heading 1
  </heading>
  this is a text for heading 1
  <a href="link"> This is a link </a>
  <div>
    <heading>
           this is heading 2
      </heading>
     this is a text for heading 2
 </div>
 <div>
    <heading>
          this is heading 2 again
    </heading>
          this is a text for heading 2 again
  </div>
</div>
</body>

Any help will be appreciated. Currenlty i have done this in asp.net but want to convert this into xslt.


Here is an XSLT 2.0 stylesheet:

<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:strip-space elements="*"/>
  <xsl:output indent="yes"/>

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

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

  <xsl:template match="*[h1]">
    <xsl:copy>
      <xsl:sequence select="mf:group(node(), 1, 3)"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="h1 | h2 | h3">
    <heading>
      <xsl:apply-templates/>
    </heading>
  </xsl:template>

</xsl:stylesheet>

When applied with Saxon 9.3 to the input

<body>
 <h1>
    heading 1
 </h1>
     this is a text for heading 1
     <a href="link"> This is a link </a>
  <h2>
       this is heading 2

  </h2>
          this is a text for heading 2
  <h2>
          this is heading 2 again
  </h2>
         this is a text for heading 2 again
</body>

I get the following output

<body>
   <div>
      <heading>
    heading 1
 </heading>
     this is a text for heading 1
     <a href="link"> This is a link </a>
      <div>
         <heading>
       this is heading 2

  </heading>
          this is a text for heading 2
  </div>
      <div>
         <heading>
          this is heading 2 again
  </heading>
         this is a text for heading 2 again
</div>
   </div>
</body>

I haven't tested the XSLT with any other more complex input so test yourself and report back if you encounter any problems.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜