[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Stylesheet from a stylesheet

Subject: Re: Stylesheet from a stylesheet
From: Midsummer Sun <midsummer.sun@xxxxxxxxx>
Date: Mon, 14 Mar 2005 13:47:47 +0530
call stylesheet
Thank you so much! It looks great. I'll test it.. and see if I need
anything else.

One requirement is left - mapping namespaces in two XMLs. I'll
probably take care of it later. If you have time, you may give a
modified version of your XSLT to take care of namespaces as well. Or
probably somebody else could..

I am wondering if the tool you have written is able to generate
optimized xsl:template definitions(just like we write XSLT files
manually) and also takes care of overlapping (nested tags).. I'll have
to test it and say further..

Thanks a lot!

Best regards,

On Mon, 14 Mar 2005 07:57:40 +0000, Aron Bock <aronbock@xxxxxxxxxxx> wrote:
> Midsummer Sun,
>
> Here's how I approached it.  At first blush it seems extensible, but your
> mileage may vary.  The idea is to design a "little-language", with a
grammar
> and a processor.  Also, unfortunately, this post is rather long, and I
> couldn't make it any shorter.  While one could argue that some of the
> templates in the "processor" below could be combined, I prefer to start
with
> multiple points of abstraction.
>
> Anyway, here's our input file: x1.xml
>
>
> <x>
> <p a="1">1</p>
> <q b="2">2</q>
> </x>
>
> We want to turn it into this: x2.xml
>
> <x>
> <u><w m="1">1</w></u>
> <v n="2">2</v>
> </x>
>
> First I manually wrote a stylesheet to do this.  We start with an "identity
> transform", then supply templates to manipulate specific nodes.  Here it
is:
> x.xsl
>
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
>    <!-- Start with identity transform: copies input to output -->
>    <xsl:template match="node() | @*">
>        <xsl:copy>
>            <xsl:apply-templates select="node() | @*"/>
>        </xsl:copy>
>    </xsl:template>
>
>    <xsl:template match="x/p">
>        <u>
>            <w>
>                <xsl:apply-templates select="@*"/>
>                <xsl:apply-templates/>
>            </w>
>        </u>
>    </xsl:template>
>
>    <xsl:template match="x/p/@a">
>        <xsl:attribute name="m">
>            <xsl:value-of select="."/>
>        </xsl:attribute>
>    </xsl:template>
>
>    <xsl:template match="x/q">
>        <v>
>            <xsl:apply-templates select="@*"/>
>            <xsl:apply-templates/>
>        </v>
>    </xsl:template>
>
>    <xsl:template match="x/q/@b">
>        <xsl:attribute name="n">
>            <xsl:value-of select="."/>
>        </xsl:attribute>
>    </xsl:template>
> </xsl:stylesheet>
>
> Then I created a "mapping file" with enough information so that I could
> mechanixally generate the stylesheet above.  I opted to go with flat <map>
> elements, and to have element and attribute maps at the same level.  That's
> because I tend not to like special cases, but again this is just my
> preference.  Note that element @to mappings show just what the terminal
> element will be replaced; not the new path-from-root.  Here it is: map.xml
>
> <maps>
>    <map from="/x/p" to="u/w"/>
>    <map from="/x/p/@a" to="@m"/>
>
>    <map from="/x/q" to="v"/>
>    <map from="/x/q/@b" to="@n"/>
> </maps>
>
> Lastly I wrote a stylesheet to take map.xml as input, and to generate an
> output xml file, like x.xsl, that's a stylesheet capable of transforming
> x1.xml to x2.xml.  It imports another stylesheet; see below.  Here is
> map.xsl
>
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0"
>    xmlns:xalan="http://xml.apache.org/xalan"
>    exclude-result-prefixes="xalan">
>
>    <xsl:import href="str.tokenize.xsl"/>
>
>    <xsl:output indent="yes"/>
>
>    <xsl:template match="/">
>        <xsl:call-template name="write-stylesheet"/>
>    </xsl:template>
>
>    <xsl:template name="write-stylesheet">
>        <xsl:element name="xsl:stylesheet">
>            <xsl:attribute
> name="xmlns:xsl">http://www.w3.org/1999/XSL/Transform</xsl:attribute>
>            <xsl:attribute name="version">1.0</xsl:attribute>
>            <xsl:element name="xsl:output">
>                <xsl:attribute
> name="omit-xml-declaration">yes</xsl:attribute>
>            </xsl:element>
>
>            <xsl:call-template name="write-identity"/>
>            <xsl:apply-templates select="/maps/map"/>
>
>        </xsl:element>
>    </xsl:template>
>
>    <!-- Writes identity-transform template -->
>    <xsl:template name="write-identity">
>        <xsl:element name="xsl:template">
>            <xsl:attribute name="match">node() | @*</xsl:attribute>
>            <xsl:element name="xsl:copy">
>                <xsl:element name="xsl:apply-templates">
>                    <xsl:attribute name="select">node() | @*</xsl:attribute>
>                </xsl:element>
>            </xsl:element>
>        </xsl:element>
>    </xsl:template>
>
>    <!-- Processes each mapping -->
>    <xsl:template match="/maps/map">
>        <xsl:element name="xsl:template">
>            <xsl:attribute name="match"><xsl:value-of
> select="@from"/></xsl:attribute>
>            <xsl:call-template name="write-to">
>                <xsl:with-param name="to" select="@to"/>
>            </xsl:call-template>
>        </xsl:element>
>    </xsl:template>
>
>    <!-- Writes the "to" part of each mapping -->
>    <xsl:template name="write-to">
>        <xsl:param name="to" select="/.."/>
>        <xsl:variable name="path">
>            <xsl:call-template name="tokenize-path">
>                <xsl:with-param name="path" select="$to"/>
>            </xsl:call-template>
>        </xsl:variable>
>
>        <xsl:call-template name="write-to-path">
>            <xsl:with-param name="path"
> select="xalan:nodeset($path)/token"/>
>        </xsl:call-template>
>    </xsl:template>
>
>    <!--
>    Continuation of template "write-to"; writes the templates
>    that creates the "to" elements/attributes
>    -->
>    <xsl:template name="write-to-path">
>        <xsl:param name="path" select="/.."/>
>
>        <xsl:choose>
>            <xsl:when test="not($path)">
>                <!-- Nothing to do (not needed; here just as safeguard) -->
>            </xsl:when>
>            <!-- If attribute, this is a 1:1 transform -->
>            <xsl:when test="starts-with($path[1], '@')">
>                <xsl:element name="xsl:attribute">
>                    <xsl:attribute name="name">
>                        <xsl:value-of select="substring($path[1], 2)"/>
>                    </xsl:attribute>
>                    <xsl:element name="xsl:value-of">
>                        <xsl:attribute name="select">.</xsl:attribute>
>                    </xsl:element>
>                </xsl:element>
>            </xsl:when>
>            <!-- Must be (we assume) an element; recursively write target
> nodes, in order -->
>            <xsl:otherwise>
>                <xsl:element name="{$path[1]}">
>                    <xsl:choose>
>                        <xsl:when test="not($path[position() != 1])">
>                            <xsl:element name="xsl:apply-templates">
>                                <xsl:attribute
> name="select">@*</xsl:attribute>
>                            </xsl:element>
>                            <xsl:element name="xsl:apply-templates"/>
>                        </xsl:when>
>                        <xsl:otherwise>
>                            <xsl:call-template name="write-to-path">
>                                <xsl:with-param name="path"
> select="$path[position() != 1]"/>
>                            </xsl:call-template>
>                        </xsl:otherwise>
>                    </xsl:choose>
>                </xsl:element>
>            </xsl:otherwise>
>        </xsl:choose>
>
>    </xsl:template>
>
>    <!-- Calls an utility tokenizing template -->
>    <xsl:template name="tokenize-path">
>        <xsl:param name="path" select="/.."/>
>        <xsl:call-template name="tokenize">
>            <xsl:with-param name="string" select="$path"/>
>            <xsl:with-param name="delimiters" select="'/'"/>
>        </xsl:call-template>
>    </xsl:template>
>
> </xsl:stylesheet>
>
> The stylesheet it imports is str.tokenize.xsl.  I got it from Sal Mangano's
> "XSLT Cookbook", and he attributes it to Jeni Tennison.  Here is
> str.tokenize.xsl
>
>
> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
> version="1.0">
> <xsl:template name="tokenize">
>     <xsl:param name="string" select="''" />
>     <xsl:param name="delimiters" select="'
> '" />
>
>  <xsl:choose>
>     <!-- Nothing to do if empty string -->
>    <xsl:when test="not($string)" />
>
>     <!-- No delimiters signals character level tokenization. -->
>    <xsl:when test="not($delimiters)">
>      <xsl:call-template name="_tokenize-characters">
>        <xsl:with-param name="string" select="$string" />
>      </xsl:call-template>
>    </xsl:when>
>    <xsl:otherwise>
>      <xsl:call-template name="_tokenize-delimiters">
>        <xsl:with-param name="string" select="$string" />
>        <xsl:with-param name="delimiters" select="$delimiters" />
>      </xsl:call-template>
>    </xsl:otherwise>
>  </xsl:choose>
> </xsl:template>
>
> <xsl:template name="_tokenize-characters">
>  <xsl:param name="string" />
>  <xsl:if test="$string">
>    <token><xsl:value-of select="substring($string, 1, 1)" /></token>
>    <xsl:call-template name="_tokenize-characters">
>      <xsl:with-param name="string" select="substring($string, 2)" />
>    </xsl:call-template>
>  </xsl:if>
> </xsl:template>
>
> <xsl:template name="_tokenize-delimiters">
>  <xsl:param name="string" />
>  <xsl:param name="delimiters" />
>  <xsl:param name="last-delimit"/>
>  <!-- Extract a delimiter -->
>  <xsl:variable name="delimiter" select="substring($delimiters, 1, 1)" />
>  <xsl:choose>
>     <!-- If the delimiter is empty we have a token -->
>    <xsl:when test="not($delimiter)">
>      <token><xsl:value-of select="$string"/></token>
>    </xsl:when>
>     <!-- If the string contains at least one delimiter we must split it -->
>    <xsl:when test="contains($string, $delimiter)">
>      <!-- If it starts with the delimiter we don't need to handle the -->
>       <!-- before part -->
>      <xsl:if test="not(starts-with($string, $delimiter))">
>         <!-- Handle the part that comes befor the current delimiter -->
>         <!-- with the next delimiter. If ther is no next the first test -->
>         <!-- in this template will detect the token -->
>        <xsl:call-template name="_tokenize-delimiters">
>          <xsl:with-param name="string"
>                          select="substring-before($string, $delimiter)" />
>          <xsl:with-param name="delimiters"
>                          select="substring($delimiters, 2)" />
>        </xsl:call-template>
>      </xsl:if>
>       <!-- Handle the part that comes after the delimiter using the -->
>       <!-- current delimiter -->
>      <xsl:call-template name="_tokenize-delimiters">
>        <xsl:with-param name="string"
>                        select="substring-after($string, $delimiter)" />
>        <xsl:with-param name="delimiters" select="$delimiters" />
>      </xsl:call-template>
>    </xsl:when>
>    <xsl:otherwise>
>       <!-- No occurances of current delimiter so move on to next -->
>      <xsl:call-template name="_tokenize-delimiters">
>        <xsl:with-param name="string"
>                        select="$string" />
>        <xsl:with-param name="delimiters"
>                        select="substring($delimiters, 2)" />
>      </xsl:call-template>
>    </xsl:otherwise>
>  </xsl:choose>
> </xsl:template>
> </xsl:stylesheet>
>
> Regards,
>
> --A
>
> _________________________________________________________________
> Is your PC infected? Get a FREE online computer virus scan from McAfee.
> Security. http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.