XSLT 2.0 question: wrapping in an arbitrary number of elements

Discussion in 'XML' started by Stryder, Mar 9, 2009.

  1. Stryder

    Stryder Guest

    Hi. I'm writing XSLT 2.0 templates and am trying to do the following
    without writing extension functions. I'm trying to go from this...

    <outer>
    <wrapin>one two three</wrapin>
    <wrapme>some text</wrapme>
    </outer>

    to this...

    <outer>
    <one>
    <two>
    <three>some text</three>
    </two>
    </one>
    </outer>

    wrapping the text in <wrapme> in an arbitrary number of elements based
    on and named after the text nodes under <wrapin>. I can't figure out
    a way to do this. I'm getting fairly well versed in XSLT 2.0,
    including using regular expressions and the new grouping elements/
    functions but I haven't figured out a way to do this. Any help would
    be appreciated.

    Thanks.
     
    Stryder, Mar 9, 2009
    #1
    1. Advertising

  2. Stryder wrote:
    > Hi. I'm writing XSLT 2.0 templates and am trying to do the following
    > without writing extension functions. I'm trying to go from this...
    >
    > <outer>
    > <wrapin>one two three</wrapin>
    > <wrapme>some text</wrapme>
    > </outer>
    >
    > to this...
    >
    > <outer>
    > <one>
    > <two>
    > <three>some text</three>
    > </two>
    > </one>
    > </outer>
    >
    > wrapping the text in <wrapme> in an arbitrary number of elements based
    > on and named after the text nodes under <wrapin>. I can't figure out
    > a way to do this. I'm getting fairly well versed in XSLT 2.0,
    > including using regular expressions and the new grouping elements/
    > functions but I haven't figured out a way to do this. Any help would
    > be appreciated.


    Here is a solution using a recursive function:

    <xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:mh="http://example.com/2009/mh"
    exclude-result-prefixes="mh xsd"
    version="2.0">

    <xsl:eek:utput method="xml" indent="yes"/>

    <xsl:template match="outer">
    <xsl:copy>
    <xsl:apply-templates select="wrapin"/>
    </xsl:copy>
    </xsl:template>

    <xsl:function name="mh:wrap" as="element()*">
    <xsl:param name="el-names" as="xsd:string*"/>
    <xsl:param name="text" as="xsd:string"/>
    <xsl:if test="exists($el-names[1])">
    <xsl:element name="{$el-names[1]}">
    <xsl:choose>
    <xsl:when test="not(exists($el-names[2]))">
    <xsl:value-of select="$text"/>
    </xsl:when>
    <xsl:eek:therwise>
    <xsl:sequence select="mh:wrap($el-names[position() gt 1],
    $text)"/>
    </xsl:eek:therwise>
    </xsl:choose>
    </xsl:element>
    </xsl:if>
    </xsl:function>

    <xsl:template match="wrapin">
    <xsl:sequence select="mh:wrap(tokenize(., '\s+'),
    data(following-sibling::wrapme[1]))"/>
    </xsl:template>

    </xsl:stylesheet>


    --

    Martin Honnen
    http://JavaScript.FAQTs.com/
     
    Martin Honnen, Mar 9, 2009
    #2
    1. Advertising

  3. Stryder

    Stryder Guest

    On Mar 9, 12:53 pm, Martin Honnen <> wrote:
    > Stryder wrote:
    > > Hi.  I'm writing XSLT 2.0 templates and am trying to do the following
    > > without writing extension functions.  I'm trying to go from this...

    >
    > > <outer>
    > >     <wrapin>one two three</wrapin>
    > >     <wrapme>some text</wrapme>
    > > </outer>

    >
    > > to this...

    >
    > > <outer>
    > >     <one>
    > >         <two>
    > >             <three>some text</three>
    > >         </two>
    > >     </one>
    > > </outer>

    >
    > > wrapping the text in <wrapme> in an arbitrary number of elements based
    > > on and named after the text nodes under <wrapin>.  I can't figure out
    > > a way to do this.  I'm getting fairly well versed in XSLT 2.0,
    > > including using regular expressions and the new grouping elements/
    > > functions but I haven't figured out a way to do this.  Any help would
    > > be appreciated.

    >
    > Here is a solution using a recursive function:
    >
    > <xsl:stylesheet
    >    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    >    xmlns:mh="http://example.com/2009/mh"
    >    exclude-result-prefixes="mh xsd"
    >    version="2.0">
    >
    >    <xsl:eek:utput method="xml" indent="yes"/>
    >
    >    <xsl:template match="outer">
    >      <xsl:copy>
    >        <xsl:apply-templates select="wrapin"/>
    >      </xsl:copy>
    >    </xsl:template>
    >
    >    <xsl:function name="mh:wrap" as="element()*">
    >      <xsl:param name="el-names" as="xsd:string*"/>
    >      <xsl:param name="text" as="xsd:string"/>
    >      <xsl:if test="exists($el-names[1])">
    >          <xsl:element name="{$el-names[1]}">
    >            <xsl:choose>
    >              <xsl:when test="not(exists($el-names[2]))">
    >                <xsl:value-of select="$text"/>
    >              </xsl:when>
    >              <xsl:eek:therwise>
    >                <xsl:sequence select="mh:wrap($el-names[position() gt 1],
    > $text)"/>
    >              </xsl:eek:therwise>
    >            </xsl:choose>
    >          </xsl:element>
    >      </xsl:if>
    >    </xsl:function>
    >
    >    <xsl:template match="wrapin">
    >      <xsl:sequence select="mh:wrap(tokenize(., '\s+'),
    > data(following-sibling::wrapme[1]))"/>
    >    </xsl:template>
    >
    > </xsl:stylesheet>
    >
    > --
    >
    >         Martin Honnen
    >        http://JavaScript.FAQTs.com/


    Thanks that's just what I needed.
     
    Stryder, Mar 9, 2009
    #3
  4. Stryder

    Stryder Guest

    On Mar 9, 12:53 pm, Martin Honnen <> wrote:
    > Stryder wrote:
    > > Hi.  I'm writing XSLT 2.0 templates and am trying to do the following
    > > without writing extension functions.  I'm trying to go from this...

    >
    > > <outer>
    > >     <wrapin>one two three</wrapin>
    > >     <wrapme>some text</wrapme>
    > > </outer>

    >
    > > to this...

    >
    > > <outer>
    > >     <one>
    > >         <two>
    > >             <three>some text</three>
    > >         </two>
    > >     </one>
    > > </outer>

    >
    > > wrapping the text in <wrapme> in an arbitrary number of elements based
    > > on and named after the text nodes under <wrapin>.  I can't figure out
    > > a way to do this.  I'm getting fairly well versed in XSLT 2.0,
    > > including using regular expressions and the new grouping elements/
    > > functions but I haven't figured out a way to do this.  Any help would
    > > be appreciated.

    >
    > Here is a solution using a recursive function:
    >
    > <xsl:stylesheet
    >    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    >    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    >    xmlns:mh="http://example.com/2009/mh"
    >    exclude-result-prefixes="mh xsd"
    >    version="2.0">
    >
    >    <xsl:eek:utput method="xml" indent="yes"/>
    >
    >    <xsl:template match="outer">
    >      <xsl:copy>
    >        <xsl:apply-templates select="wrapin"/>
    >      </xsl:copy>
    >    </xsl:template>
    >
    >    <xsl:function name="mh:wrap" as="element()*">
    >      <xsl:param name="el-names" as="xsd:string*"/>
    >      <xsl:param name="text" as="xsd:string"/>
    >      <xsl:if test="exists($el-names[1])">
    >          <xsl:element name="{$el-names[1]}">
    >            <xsl:choose>
    >              <xsl:when test="not(exists($el-names[2]))">
    >                <xsl:value-of select="$text"/>
    >              </xsl:when>
    >              <xsl:eek:therwise>
    >                <xsl:sequence select="mh:wrap($el-names[position() gt 1],
    > $text)"/>
    >              </xsl:eek:therwise>
    >            </xsl:choose>
    >          </xsl:element>
    >      </xsl:if>
    >    </xsl:function>
    >
    >    <xsl:template match="wrapin">
    >      <xsl:sequence select="mh:wrap(tokenize(., '\s+'),
    > data(following-sibling::wrapme[1]))"/>
    >    </xsl:template>
    >
    > </xsl:stylesheet>
    >
    > --
    >
    >         Martin Honnen
    >        http://JavaScript.FAQTs.com


    Here's another one...

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/
    Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsl:eek:utput method="xml" indent="yes"/>

    <xsl:template match="/">
    <xsl:variable name="names" select="('one', 'two', 'three')"/>
    <xsl:call-template name="wrapem">
    <xsl:with-param name="names_param" select="('one', 'two',
    'three')"/>
    <xsl:with-param name="text_param"><xsl:text>some text to
    put in the element</xsl:text></xsl:with-param>
    </xsl:call-template>
    </xsl:template>

    <xsl:template name="wrapem">
    <xsl:param name="names_param"/>
    <xsl:param name="text_param"/>
    <xsl:for-each select="$names_param[position()=1]">
    <xsl:variable name="element_name" select="."/>
    <xsl:element name="{$element_name}">
    <xsl:if test="count($names_param) = 1">
    <xsl:value-of select="text_param"/>
    </xsl:if>
    <xsl:call-template name="wrapem"><xsl:with-param
    name="names_param" select="$names_param[position() != 1]"/></xsl:call-
    template>
    </xsl:element>
    </xsl:for-each>
    </xsl:template>
    </xsl:stylesheet>
     
    Stryder, Mar 10, 2009
    #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. Ankur Bulsara
    Replies:
    0
    Views:
    462
    Ankur Bulsara
    Apr 23, 2004
  2. Marcel Akkerman
    Replies:
    5
    Views:
    875
    Marcel Akkerman
    Feb 22, 2004
  3. Honestmath
    Replies:
    5
    Views:
    562
    Honestmath
    Dec 13, 2004
  4. Gerald Aichholzer
    Replies:
    2
    Views:
    2,513
    Gerald Aichholzer
    Jun 27, 2006
  5. Zachary  Turner
    Replies:
    1
    Views:
    529
    Bjoern Hoehrmann
    May 30, 2007
Loading...

Share This Page