Home. 
.

transparent

transparent

transparent

Altova Mailing List Archives


Re: multi step transformation

From: "Marrow" <m--a-r-r-o-w@--------------------.--->
To: NULL
Date: 10/2/2004 10:46:00 AM
Hi,

Seeing as you will need to modify your generic split routine anyway (as it
currently will not work correctly - the "Add all the attributes this bit not
tested" will never work because you are trying to output attributes after
you have output element content) the best approach would probably be to add
some generic capabilities to that template to cater for any optional
additional processing you might want to do when splitting.

You could employ a 'callback' technique - whereby you pass an element as a
param to your named template (usually an element with a discrete namespace
binding) and then apply templates to that passed element from within your
generic routine.  The template that matches that element will then be your
'callback' routine that will do any additional specific processing for this
call to the generic template.

An example (using the same well-formed XML I gave previously as the test)...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="my-callbacks"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:my-callbacks="urn:my-callbacks">

  <!-- define the callbacks - there will be one element in the list for
every -->
  <!-- special process that you want to carry out -->
  <my-callbacks:list>
    <my-callbacks:add-b-attribute/>
  </my-callbacks:list>
  <!-- pull the callbacks into a variable for use later -->
  <xsl:variable name="callbacks" select="document('')/*/my-callbacks:list"/>

  <xsl:template match="/">
    <output>
      <xsl:apply-templates select="item"/>
    </output>
  </xsl:template>

  <xsl:template match="item">
    <xsl:call-template name="split">
      <xsl:with-param name="elem" select="a"/>
      <xsl:with-param name="input" select="string(a)"/>
      <xsl:with-param name="delimiter" select="'&#10;'"/>
      <xsl:with-param name="callback"
select="$callbacks/my-callbacks:add-b-attribute"/>
    </xsl:call-template>
  </xsl:template>

  <!-- callback routine for adding the @b attribute -->
  <xsl:template match="my-callbacks:add-b-attribute">
    <xsl:param name="elem"/>
    <xsl:attribute name="b">
      <xsl:value-of select="$elem/../b"/>
    </xsl:attribute>
  </xsl:template>

  <!-- generic split routine -->
  <xsl:template name="split">
    <xsl:param name="elem"/>
    <xsl:param name="input"/>
    <xsl:param name="delimiter" select="'&#10;'"/>
    <xsl:param name="callback"/> <!-- if this param is not passed there will
be no added processing -->
    <xsl:choose>
      <!-- See if the input contains the search string -->
      <xsl:when test="contains($input, $delimiter)">
        <xsl:element name="{name($elem)}"
namespace="{namespace-uri($elem)}">
          <!-- add all the attributes this bit -->
          <xsl:copy-of select="$elem/@*"/>
          <xsl:if test="$callback">
            <!-- perform an additional processing in the callback -->
            <xsl:apply-templates select="$callback">
              <xsl:with-param name="elem" select="$elem"/>
            </xsl:apply-templates>
          </xsl:if>
          <!-- output spliced part of value -->
          <xsl:value-of
select="normalize-space(substring-before($input,$delimiter))"/>
        </xsl:element>
        <xsl:call-template name="split">
          <xsl:with-param name="elem" select="$elem"/>
          <xsl:with-param name="input"
select="substring-after($input,$delimiter)"/>
          <xsl:with-param name="delimiter" select="$delimiter"/>
          <xsl:with-param name="callback" select="$callback"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="normalize-space($input)">
        <xsl:element name="{name($elem)}"
namespace="{namespace-uri($elem)}">
          <!-- add all the attributes this bit -->
          <xsl:copy-of select="$elem/@*"/>
          <xsl:if test="$callback">
            <!-- perform an additional processing in the callback -->
            <xsl:apply-templates select="$callback">
              <xsl:with-param name="elem" select="$elem"/>
            </xsl:apply-templates>
          </xsl:if>
          <!-- output spliced part of value -->
          <xsl:value-of select="normalize-space($input)"/>
        </xsl:element>
      </xsl:when>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>


HTH
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator


"wooks" <wookiz@h...> wrote in message
news:8852d33c.0410012329.1e30fc84@p......
>
> Memo to self - when asking for help be more explicit.
>
> Below is my generic split routine (the input parameter is probably
> otiose as it is just the text value of the element passed). It passes
> the element to be split as well as the delimiter to split by. I want
> each element created to have a copy of all the attributes that the
> unsplit element had (as per the comments the xsl:for-each to  handle
> this is as yet untested).
>
> The difficulty is that the input XML doesn't have any attribute nodes.
> In this particular instance it is in element b, but the split routine
> will no longer be generic if I pass it specific elements to be
> converted to attributes (and there could be more than one element that
> needs to be so converted).
>
> So the constraints are -
> 1. Using the generic splitter which can be amended but not in a way as
> to lose genericity.
> 2. Avoid a 2 step transformation.
>
> The alternative is to accept that a generic routine cannot do this in
> one pass, but something in my brain tells me XSLT should be capable of
> better than that, I  don't know how though.
>
>
>
>
>
> <xsl:stylesheet
>   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>   version="1.0">
>   <xsl:template name="split">
>   <xsl:param name="elem"/>
>   <xsl:param name="input"/>
>   <xsl:param name="delimiter"/>
>   <xsl:choose>
>   <!-- See if the input contains the search string -->
>   <xsl:when test="contains($input, $delimiter)">
>   <xsl:element name="{name($elem)}"
> namespace="{namespace-uri($elem)}">
>   <xsl:value-of select="normalize-space(substring-before($input,
> $delimiter))"/>
>   <!-- Add all the attributes this bit not tested-->
>   <xsl:for-each select="$elem/@*">
>   <xsl:attribute name="name(current())">
>   <xsl:value-of select="current()"/>
>   </xsl:attribute>
>   </xsl:for-each>
>   </xsl:element>
>   <xsl:call-template name="split">
>   <xsl:with-param name="elem" select="$elem"/>
>   <xsl:with-param name="input" select="substring-after($input,
> $delimiter)"/>
>   <xsl:with-param name="delimiter" select="$delimiter"/>
>   </xsl:call-template>
>   </xsl:when>
>   <xsl:otherwise>
>   <xsl:element name="{name($elem)}"
> namespace="{namespace-uri($elem)}">
>   <xsl:value-of select="$input"/>
>   </xsl:element>
>   </xsl:otherwise>
>   </xsl:choose>
>   </xsl:template>
> </xsl:stylesheet>




transparent
Print
Mail
Like It
Disclaimer
.

These Archives are provided for informational purposes only and have been generated directly from the Altova mailing list archive system and are comprised of the lists set forth on www.altova.com/list/index.html. Therefore, Altova does not warrant or guarantee the accuracy, reliability, completeness, usefulness, non-infringement of intellectual property rights, or quality of any content on the Altova Mailing List Archive(s), regardless of who originates that content. You expressly understand and agree that you bear all risks associated with using or relying on that content. Altova will not be liable or responsible in any way for any content posted including, but not limited to, any errors or omissions in content, or for any losses or damage of any kind incurred as a result of the use of or reliance on any content. This disclaimer and limitation on liability is in addition to the disclaimers and limitations contained in the Website Terms of Use and elsewhere on the site.

.
.

transparent

transparent