xsl-list
[Top] [All Lists]

Re: [xsl] Group Techniques by xslt

2009-12-02 13:11:41
Joga Singh Rawat wrote:

If someone have a logic to structure a data of unstructred file, please
help. I am clueless. I am new in xslt 2.0.

Here is a partial solution:

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  version="2.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema";
  xmlns:mf="http://example.com/2009/mf";
  exclude-result-prefixes="xsd mf">

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

  <xsl:function name="mf:group" as="node()*">
    <xsl:param name="elements" as="element()*"/>
    <xsl:param name="level" as="xsd:integer"/>

<xsl:for-each-group select="$elements" group-starting-with="p[(_at_)class eq concat('Head', $level)]">
      <xsl:element name="sc{$level}">

        <xsl:variable name="current-head" as="element()?"
          select="self::p[(_at_)class eq concat('Head', $level)]"/>

        <xsl:apply-templates select="$current-head"/>

        <xsl:variable name="max-level"
select="max(for $h in current-group()[self::p[matches(@class, '^Head[0-9]+$')]]
                  return xsd:integer(substring($h/@class, 5)))"/>

        <xsl:variable name="next-head" as="element()?"
select="current-group()[self::p[matches(@class, '^Head[0-9]+$')]][1]"/>

        <xsl:variable name="v1" as="element()*"
select="current-group()[. &lt;&lt; $next-head] except $current-head"/>

        <xsl:apply-templates select="$v1"/>

        <xsl:choose>
          <xsl:when test="$level lt $max-level">
<xsl:sequence select="mf:group(current-group() except ($current-head, $v1), $level + 1)"/>
          </xsl:when>
          <xsl:otherwise>
<xsl:apply-templates select="current-group() except $current-head"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:element>
    </xsl:for-each-group>
  </xsl:function>

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

  <xsl:template match="div[(_at_)class='bdy']">
    <bdy>
      <xsl:variable name="v1" as="element()*"
select="*[. &lt;&lt; (current()/p[(_at_)class eq 'Head1' or @class eq 'Head2'])[1]]"/>
      <xsl:apply-templates select="$v1"/>
      <xsl:sequence select="mf:group(* except $v1, 1)"/>
    </bdy>
  </xsl:template>

  <xsl:template match="p[matches(@class, '^Head[0-9]+$')]">
    <ti>
      <xsl:apply-templates/>
    </ti>
  </xsl:template>

  <xsl:template match="p[(_at_)class eq 'Para_FL']">
    <p t="f1">
      <xsl:apply-templates/>
    </p>
  </xsl:template>

</xsl:stylesheet>

It does not quite output what you want as you seem to want to group initially with group-starting-with="p[(_at_)class='Head1']|p[(_at_)class='Head2'] while the stylesheet above uses a single function that groups level by level (i.e. 'Head1', then 'Head2', then 'Head3' and so on). I am not sure there is an elegant way to fix that, other than implementing a second function for the special case of the initial grouping you want.



--

        Martin Honnen
        http://msmvps.com/blogs/martin_honnen/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--