Re: [xsl] xsl transormation from flat tree to hierarchical tree

Subject: Re: [xsl] xsl transormation from flat tree to hierarchical tree
From: Andreas Volz <lists@xxxxxxxxxxxxx>
Date: Sun, 18 Mar 2012 11:30:47 +0100
Am Sat, 10 Mar 2012 16:00:47 +0530 schrieb Mukul Gandhi:

Hi Mukul,

thanks for that hints! I never used that call-templates before. After
some experiments I got it somehow running in my xsl:

o;?<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

<xsl:template name="printStateTree"
xmlns:dotml="http://www.martin-loetzsch.de/DOTML";>
     <xsl:param name="curState"/>

      <xsl:element name="node">

          <xsl:attribute name="id"><xsl:value-of select="$curState/@name"/>
          </xsl:attribute>

          <xsl:attribute name="label"><xsl:value-of
select="$curState/@name"/>
          </xsl:attribute>

          <xsl:attribute name="fontname">Arial</xsl:attribute>

          <xsl:attribute name="fontsize">9</xsl:attribute>

          <xsl:for-each select="//state[@parent = $curState/@name]">

              <xsl:call-template name="printStateTree">
                  <xsl:with-param name="curState" select="."/>
              </xsl:call-template>

         </xsl:for-each>

      </xsl:element>

</xsl:template>

<xsl:template match="/">
    <dotml:graph file-name="stateval"
xmlns:dotml="http://www.martin-loetzsch.de/DOTML";
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
      xsi:schemaLocation="http://www.martin-loetzsch.de/DotML
../dotml-1.3/dotml-1.3.xsd" label="stateval" fontcolor="#0000A0"
fontname="Arial Bold" margin="0.2,0.1" ranksep="0.2" nodesep="0.5"
      bgcolor="#F0F0FF" fontsize="13" style="dashed">

        <xsl:for-each select="stateval/states">

          <xsl:call-template name="printStateTree">
               <xsl:with-param name="curState" select="state[not(@parent)]"/>
          </xsl:call-template>

        </xsl:for-each>

        <xsl:for-each select="stateval/transitions/transition">
            <dotml:edge>
                <xsl:attribute name="from"><xsl:value-of select="@from"/>
                </xsl:attribute>

                <xsl:attribute name="to"><xsl:value-of select="@to"/>
                </xsl:attribute>

                <xsl:attribute name="label"><xsl:value-of select="@event"/>
                </xsl:attribute>

                <xsl:attribute name="fontname">Arial</xsl:attribute>

                <xsl:attribute name="fontsize">7</xsl:attribute>
            </dotml:edge>
        </xsl:for-each>

    </dotml:graph>
</xsl:template>

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


</xsl:stylesheet>

But the output is still not as I need it:

<?xml version="1.0"?>
<dotml:graph xmlns:dotml="http://www.martin-loetzsch.de/DOTML";
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; file-name="stateval"
xsi:schemaLocation="http://www.martin-loetzsch.de/DotML
../dotml-1.3/dotml-1.3.xsd" label="stateval" fontcolor="#0000A0"
fontname="Arial Bold" margin="0.2,0.1" ranksep="0.2" nodesep="0.5"
bgcolor="#F0F0FF" fontsize="13" style="dashed">
    <node id="Root" label="Root" fontname="Arial" fontsize="9">
        <node id="Initial" label="Initial" fontname="Arial" fontsize="9" />
        <node id="Final" label="Final" fontname="Arial" fontsize="9" />
        <node id="Main" label="Main" fontname="Arial" fontsize="9" />
        <node id="Browser" label="Browser" fontname="Arial" fontsize="9" />
        <node id="Settings" label="Settings" fontname="Arial" fontsize="9" />
        <node id="EMail_Compound" label="EMail_Compound" fontname="Arial"
fontsize="9">
            <node id="EMail_Compound_Initial" label="EMail_Compound_Initial"
fontname="Arial" fontsize="9" />
            <node id="EMail_Compound_History" label="EMail_Compound_History"
fontname="Arial" fontsize="9" />
            <node id="EMail_Read" label="EMail_Read" fontname="Arial"
fontsize="9" />
            <node id="EMail_Compose" label="EMail_Compose" fontname="Arial"
fontsize="9" />
        </node>
    </node>
    <dotml:edge from="Initial" to="Main" label="" fontname="Arial"
fontsize="7" />
    <dotml:edge from="Root" to="Final" label="EXIT" fontname="Arial"
fontsize="7" />
    <dotml:edge from="Root" to="Main" label="MAIN" fontname="Arial"
fontsize="7" />
    <dotml:edge from="Root" to="Browser" label="BROWSER" fontname="Arial"
fontsize="7" />
    <dotml:edge from="Root" to="Settings" label="SETTINGS" fontname="Arial"
fontsize="7" />
    <dotml:edge from="Root" to="EMail_Compound" label="EMAIL" fontname="Arial"
fontsize="7" />
    <dotml:edge from="EMail_Compound" to="EMail_Compound_Initial" label=""
fontname="Arial" fontsize="7" />
    <dotml:edge from="EMail_Compound_Initial" to="EMail_Compound_History"
label="" fontname="Arial" fontsize="7" />
    <dotml:edge from="EMail_Compound_History" to="EMail_Read" label=""
fontname="Arial" fontsize="7" />
    <dotml:edge from="EMail_Compound" to="EMail_Compose" label="EMAIL_COMPOSE"
fontname="Arial" fontsize="7" />
    <dotml:edge from="EMail_Compound" to="EMail_Read" label="EMAIL_READ"
fontname="Arial" fontsize="7" />
</dotml:graph>

It has now correct transformation into a parent relation, but dotml needs
format like this:

<record	>
  <node 	id="10" label="left"/>
  <node 	id="11" label="middle"/>
  <node 	id="12" label="right"/>
</record>

<record	>
  <node 	id="20" label="one"/>
  <node 	id="21" label="two"/>
</record>

I tried to learn more about xsl by reading w3schools docu, but I wasn't able
to
get exact that result. So I like to have this:

Could you maybe give me please another hint?

regards
  Andreas

> Hi Andreas,
>     May I propose a solution, which may be a start.
>
> I guess, your area of interest for transformation is following XML
> fragment (which is the only place, where I can see the "parent"
> attribute),
>
> <states>
>     <state name="root" type="CompoundState"/>
>     <state name="a" type="SimpleState" parent="root"/>
>     <state name="choose" type="DecisionState" parent="root"/>
>     <state name="b" type="SimpleState" parent="root"/>
>     <state name="c" type="SimpleState" parent="root"/>
> </states>
>
> So here's my proposal for this transformation,
>
> <!-- starting point -->
> <xsl:call-template name="printStateTree">
>      <xsl:with-param name="curState" select="state[not(@parent)]"/>
> </xsl:call-template>
>
> <xsl:template name="printStateTree">
>      <xsl:param name="curState"/>
>
>      <xsl:element name="{$curState/@name}"/>
>           <xsl:for-each select="//state[@parent = $curState/@name]">
>               <xsl:call-template name="printStateTree">
>                   <xsl:with-param name="curState" select="."/>
>               </xsl:call-template>
>          </xsl:for-each>
>      </xsl:element>
> </xsl:template>
>
> This is not tested. The output format of this XSLT fragment is
> unrelated to your actual output (and it is not optimized -- since it
> has the expression //state, and output probably not normalized to be a
> good tree format). This XSLT fragment only intends to demonstrate the
> technique that I had in mind.
>
> Just some food for thought :)
>
>
> On Sat, Mar 10, 2012 at 1:44 PM, Andreas Volz <lists@xxxxxxxxxxxxx>
> wrote:
> > Am Sat, 3 Mar 2012 11:21:09 +0100 schrieb Andreas Volz:
> >
> >> Hello,
> >>
> >> I've a list with a flat tree that has a parent attribute to save
> >> child/father relations.
> >>
> >>
http://stateval.googlecode.com/svn/trunk/stateval/test/features/ft2.smxml
> >>
> >> I just like to transform this state machine graph in DotML format
> >> to display it as SVG:
> >>
> >> http://martin-loetzsch.de/DOTML/record.html
> >>
> >> I've yet a somehow working version:
> >>
> >>
http://stateval.googlecode.com/svn/trunk/stateval/doc/graph_gen/stateval_dotm
l.xsl
> >>
> >> But it has only a flat list and shows transitions between them. I
> >> would like to handle CompoundStates as records in DotML. So I need
> >> some transformation from my flat tree into that hierarchical tree
> >> from DotML record.
> >>
> >> I've no idea how to do this in xsl. I'm using xsltproc in Ubuntu
> >> 11.10:
> >>
> >> > xsltproc --version
> >> Using libxml 20708, libxslt 10126 and libexslt 815
> >> xsltproc was compiled against libxml 20708, libxslt 10126 and
> >> libexslt 815 libxslt 10126 was compiled against libxml 20708
> >> libexslt 815 was compiled against libxml 20708
> >>
> >> As fas as I know it supports only XSLT 1.0.
> >>
> >> Could you help me?
> >
> > No hints? Did I ask in a wrong way? Or isn't this possible?
> >
> > regards
> > B  B  B  B Andreas
> >
> >
> > --
> > Technical Blog <http://andreasvolz.wordpress.com/>
>
>
>
>
> --
> Regards,
> Mukul Gandhi
>


--
Technical Blog <http://andreasvolz.wordpress.com/>

Current Thread