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

Reply via email to