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[@class eq concat('Head', $level)]">
<xsl:element name="sc{$level}">
<xsl:variable name="current-head" as="element()?"
select="self::p[@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()[. << $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[@class='bdy']">
<bdy>
<xsl:variable name="v1" as="element()*"
select="*[. << (current()/p[@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[@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[@class='Head1']|p[@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/