At 2010-01-07 11:55 +0530, anuj kumar wrote:
I have an xml of the form
...
A change in the designator(Designators may be in alpha, numeric,
roman, alpha-numeric,
etc bounded or unbounded by brackets) format must be used as basis
for identifying the primary level.
I've implemented this so you can use regular expressions to determine
the level indications.
Designators in sequence or series must be treated as primary level
text of the same level. For example:
(a)-first level
(b)-first level
(c)-first level
I have to create the following output xml out of the above input xml:
...
Pleae advise, how to do this?
You don't share with us what you have tried and what has not worked for you.
I have a complete solution below. I found it easier to think first
in XSLT because of the grouping facilities that are available, and
then to just transliterate that into XQuery for a pure-XQuery solution.
Note that readers may find it interesting to have to do the following
in XQuery:
(<tree>{elements-expression}</tree>)/*
... in order to create a sibling relationship between a copy of nodes
so that the recursive use of the following-sibling axis would not
access the original nodes. Simply referencing the nodes isn't
sufficient because the nodes retain their original location in the
original tree.
I hope this helps.
. . . . . . . . . . . . Ken
T:\ftemp>type anuj.xml
<doc>
<p>(a)- first level </p>
<p>(1)- second level</p>
<p>(2)- second level</p>
<p>(A)- third level</p>
<p>(B)- third level</p>
<p>(3)- second level</p>
<p>(b)- first level</p>
</doc>
T:\ftemp>call xslt2 anuj.xml anuj.xsl
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<parent>
<title>(a)- first level </title>
<child>
<title>(1)- second level</title>
</child>
<child>
<title>(2)- second level</title>
<child>
<title>(A)- third level</title>
</child>
<child>
<title>(B)- third level</title>
</child>
</child>
<child>
<title>(3)- second level</title>
</child>
</parent>
<parent>
<title>(b)- first level</title>
</parent>
</doc>
T:\ftemp>call xquery anuj.xq
<?xml version="1.0" encoding="UTF-8"?>
<doc>
<parent>
<title>(a)- first level </title>
<child>
<title>(1)- second level</title>
</child>
<child>
<title>(2)- second level</title>
<child>
<title>(A)- third level</title>
</child>
<child>
<title>(B)- third level</title>
</child>
</child>
<child>
<title>(3)- second level</title>
</child>
</parent>
<parent>
<title>(b)- first level</title>
</parent>
</doc>
T:\ftemp>type anuj.xsl
<?xml version="1.0" encoding="US-ASCII"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"/>
<xsl:variable name="patterns" as="element(patterns)">
<patterns>
<pattern>^\([a-z]\)</pattern>
<pattern>^\([\d+]\)</pattern>
<pattern>^\([A-Z]\)</pattern>
</patterns>
</xsl:variable>
<xsl:template match="doc">
<doc>
<xsl:call-template name="parent">
<xsl:with-param name="population" select="p"/>
<xsl:with-param name="pattern" select="$patterns/pattern[1]"/>
<xsl:with-param name="relationship" select="'parent'"/>
</xsl:call-template>
</doc>
</xsl:template>
<xsl:template name="parent">
<xsl:param name="population"/>
<xsl:param name="pattern"/>
<xsl:param name="relationship"/>
<xsl:if test="$population">
<!--only do something if there is something to do-->
<xsl:choose>
<xsl:when test="not($pattern)">
<!--no more depth-->
<xsl:for-each select="$population">
<xsl:element name="{$relationship}">
<title><xsl:copy-of select="node()"/></title>
</xsl:element>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<!--process next level of depth-->
<xsl:for-each-group select="$population"
group-starting-with="*[matches(.,$pattern)]">
<xsl:element name="{$relationship}">
<title><xsl:copy-of select="node()"/></title>
<xsl:call-template name="parent">
<xsl:with-param name="population"
select="current-group()[position()>1]"/>
<xsl:with-param name="pattern"
select="$pattern/following-sibling::*[1]"/>
<xsl:with-param name="relationship" select="'child'"/>
</xsl:call-template>
</xsl:element>
</xsl:for-each-group>
</xsl:otherwise>
</xsl:choose>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
T:\ftemp>type anuj.xq
declare namespace a = "urn:X-anuj";
declare variable $patterns as element(patterns) :=
<patterns>
<pattern>^\([a-z]\)</pattern>
<pattern>^\([\d+]\)</pattern>
<pattern>^\([A-Z]\)</pattern>
</patterns>;
declare function a:parent( $population, $pattern, $relationship )
{
if( $population )
then
(: only do something if there is something to do :)
if( not($pattern) )
then
(: no more depth :)
for $each in $population return
element {$relationship} {<title>{$each/node()}</title>}
else
(: process next level of depth :)
for $level in $population[matches(.,$pattern)]
return
element {$relationship}
{
<title>{$level/node()}</title>,
a:parent( (<tree>
{$level/following-sibling::* except
$level/following-sibling::*[matches(.,$pattern)][1]/
(self::* |
following-sibling::* )
}
</tree>)/* (:create a new tree of children:),
$pattern/following-sibling::*[1] (:the next pattern:),
'child' )
}
else ()
};
<doc>{a:parent( doc('anuj.xml')/doc/p, $patterns/pattern[1], 'parent' )}</doc>
T:\ftemp>rem Done!
--
UBL and Code List training: Copenhagen, Denmark 2010-02-08/10
XSLT/XQuery/XPath training after http://XMLPrague.cz 2010-03-15/19
XSLT/XQuery/XPath training: San Carlos, California 2010-04-26/30
Vote for your XML training: http://www.CraneSoftwrights.com/q/i/
Crane Softwrights Ltd. http://www.CraneSoftwrights.com/q/
Training tools: Comprehensive interactive XSLT/XPath 1.0/2.0 video
Video lesson: http://www.youtube.com/watch?v=PrNjJCh7Ppg&fmt=18
Video overview: http://www.youtube.com/watch?v=VTiodiij6gE&fmt=18
G. Ken Holman mailto:[email protected]
Male Cancer Awareness Nov'07 http://www.CraneSoftwrights.com/q/bc
Legal business disclaimers: http://www.CraneSoftwrights.com/legal
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general