Multiple XSLt Transforms?

Discussion in 'XML' started by rush, Mar 30, 2005.

  1. rush

    rush Guest

    I have a DTD that defines new elements "mytextfield" and "mysn", and
    does it as an extension to XHTML. The idea is that my XML markup is
    actually valid XHTML according to my DTD. This all works just fine.

    After getting the DTD to work, I defined a XSL stylesheet that would
    transform my markup into XHTML that would display correctly in a
    browser. At first this meant that everywhere I encontered a
    "mytextfield" element in the markup, I would transform it into a
    <input type="text" /> element in the output, and preserve whatever
    attributes were on the "mytextfield" element. Again, this worked just
    fine.

    My next step was to define the "mysn" element. A "mysn" is actually a
    collection of my custom elements, each of which has a XHTML (browser)
    representation. The simplified example below shows mysn as a
    mytextfield
    with a custom text label. I could have written the transform so that
    the output is in terms of standard XHTML elements, but what I want to
    do is define the mysn transformation in terms of my underlying
    elements,
    then use their transformations to create the XHTML that the browser
    will
    display nicely. This is also because I have a case where my original
    markup will be written in terms of the more abstract elements, such as
    mysn, but I need to transform it into the less abstract but still
    custom
    elements (mytextfield).

    For instance, if this is my original (simplified) markup:
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="myxform.xsl" type="text/xsl"?>
    <!DOCTYPE html SYSTEM "mydtd.dtd">
    <html><head></head>
    <body><form>
    <p><mytextfield size="30" name="FirstName" />First Name</p>
    <mysn />
    </form></body>
    </html>


    I would like the intermediate transform to be:
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="myxform.xsl" type="text/xsl"?>
    <!DOCTYPE html SYSTEM "mydtd.dtd">
    <html><head></head>
    <body><form>
    <p><mytextfield size="30" name="FirstName" />First Name</p>x
    <p><mytextfield name="NewSerialNum" size="40"/>Please enter your
    serial number</p>
    </form></body>
    </html>

    But I want the transform that the browser sees to be:
    <?xml version="1.0" encoding="UTF-8"?>
    <?xml-stylesheet href="myxform.xsl" type="text/xsl"?>
    <!DOCTYPE html SYSTEM "mydtd.dtd">
    <html><head></head>
    <body><form>
    <p><input type="text" size="30" name="FirstName" />First Name</p>
    <p><input type="text" name="NewSerialNum" size="40"/>Please enter
    your serial number</p>
    </form></body>
    </html>

    Here is the form of the XSL stylesheet that I want to use:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:eek:utput method="html" version="4.0" />

    <!--========================================================
    Template for matching an mytextfield element in a form.
    Morph it into a text input, copying some of the attributes.
    ============================================================-->
    <xsl:template match="form//mytextfield">
    <xsl:element name="input">
    <xsl:attribute name="type">
    <xsl:text>text</xsl:text>
    </xsl:attribute>

    <xsl:for-each select="@id | @size | @maxlength | @name">
    <xsl:attribute name="{name()}">
    <xsl:value-of select="." />
    </xsl:attribute>
    </xsl:for-each>

    </xsl:element>
    </xsl:template>

    <!--=================================================
    Template for matching an mysn elementiwithin a form.
    Turn it into a mytextfield with a known name
    ======================================================-->
    <xsl:template priority="1.0" match="form//mysn">
    <xsl:element name="p">
    <mytextfield name="NewSerialNum" size="40"/>
    <xsl:text>Please enter your serial number</xsl:text>
    </xsl:element>
    </xsl:template>
    </xsl:stylesheet>

    The actual usage scenario is much more complicated than this. People
    that I do not know and cannot easily interact with will be writing the
    markup. I need a way to validate what they write, but I would really
    like it if they could just display it with a web browser.

    I have spent a couple of days reading and searching the web, looking
    for examples. I have also tried using entitities, <xsl:include>, and
    variations on named templates. It looks like XSLT version 2.0 will
    handle this case, but that 1.0 probably can't. Does anyone know of
    some clever way to implement such two stage transformations using
    version 1.0?

    Thanks and sorry for the long post,
    Rush
     
    rush, Mar 30, 2005
    #1
    1. Advertising

  2. <xsl:template match="form//mytextfield">
    <xsl:element name="input">
    <xsl:attribute name="type">
    <xsl:text>text</xsl:text>
    </xsl:attribute>

    <xsl:for-each select="@id | @size | @maxlength | @name">
    <xsl:attribute name="{name()}">
    <xsl:value-of select="." />
    </xsl:attribute>
    </xsl:for-each>

    </xsl:element>
    </xsl:template>


    That could be written much more simply as

    <xsl:template match="mytextfield">
    <input type="text">
    <xsl:copy-of select="@id | @size | @maxlength | @name"/>
    </input>
    </xsl:template>


    To answer your question:

    It looks like XSLT version 2.0 will
    handle this case, but that 1.0 probably can't. Does anyone know of
    some clever way to implement such two stage transformations using
    version 1.0?

    the standard XSLT 1.0 way to do two transforms is just simply to use two
    xslt stylesheets and call one then the other. Even in a browser setting
    this is possible with a bit of javascript.

    Alternatively you may be able to do the two transforms within one
    stylesheet by first transforming into a varibale and then applying the
    templates of the second transform to that variable. this however relies
    on a node-set() extension function to convert the result tree fragment
    in the variable to a node set suitable for input to the second pass.
    Pretty much every XSLT engine has this extension (the notable exception
    being the transformiix engine in mozilla)

    David
     
    David Carlisle, Mar 30, 2005
    #2
    1. Advertising

  3. rush

    rush Guest

    Thanks for the reply, David. Comments and followup questions are
    inline, if you care to spend any more time on this. I am new to
    this XML/XSL stuff and I don't yet know what all the pieces are,
    much less how to put them all together. I really appreciate the help.

    > That could be written much more simply as
    >
    > > <xsl:template match="mytextfield">
    > > <input type="text">
    > > <xsl:copy-of select="@id | @size | @maxlength | @name"/>
    > > </input>
    > > </xsl:template>


    This is cool! I didn't realize you could use copy-of with attributes.
    Thanks.

    >
    > To answer your question:
    >
    > > It looks like XSLT version 2.0 will
    > > handle this case, but that 1.0 probably can't. Does anyone know of
    > > some clever way to implement such two stage transformations using
    > > version 1.0?

    >
    > the standard XSLT 1.0 way to do two transforms is just simply to use

    two
    > xslt stylesheets and call one then the other. Even in a browser

    setting
    > this is possible with a bit of javascript.


    You wouldn't care to elaborate a little bit here, would you?

    >
    > Alternatively you may be able to do the two transforms within one
    > stylesheet by first transforming into a varibale and then applying

    the
    > templates of the second transform to that variable. this however

    relies
    > on a node-set() extension function to convert the result tree

    fragment
    > in the variable to a node set suitable for input to the second pass.
    > Pretty much every XSLT engine has this extension (the notable

    exception
    > being the transformiix engine in mozilla)
    >
    > David


    I found this:
    http://www-106.ibm.com/developerworks/xml/library/x-tipxsltmp.html
    which showed exactly how to do this with node-set(). I tried it using
    xsltproc
    and it worked like a charm! Firefox won't deal with it (as you
    mentioned),
    but I can figure out some way to deal with that.

    - Rush
     
    rush, Mar 30, 2005
    #3

  4. > > this is possible with a bit of javascript.


    > You wouldn't care to elaborate a little bit here, would you?



    The js interface to XSLT in moz is here

    http://www.mozilla.org/projects/xslt/js-interface.html

    IE has something similar.
    Basically the idea is you use that interface to apply your first
    transform, you then get a DOM which you stuff into a second transform
    that produces a DOM with (X)HTML elements which you then allow to drop
    through to the browser's renderer.

    David
     
    David Carlisle, Mar 30, 2005
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Random

    xslt, multiple transforms

    Random, Feb 28, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    1,482
    Wilco Bauwer
    Feb 28, 2005
  2. Ian Stanley

    Help with transforms

    Ian Stanley, Jul 30, 2003, in forum: Java
    Replies:
    3
    Views:
    512
    Ian Stanley
    Jul 31, 2003
  3. Ravi
    Replies:
    4
    Views:
    377
    Dimitre Novatchev
    Nov 10, 2003
  4. Replies:
    2
    Views:
    725
    Henry S. Thompson
    Oct 19, 2005
  5. Wizfrog
    Replies:
    1
    Views:
    566
    Martin Honnen
    Jul 22, 2007
Loading...

Share This Page