Re: [xsl] Confusing namespaces and xslt

Subject: Re: [xsl] Confusing namespaces and xslt
From: Paul <pflists@xxxxxxxxx>
Date: Thu, 2 Oct 2008 15:39:06 -0400
I'm trying to insert a new element in between two existing elements. I
know that mode="content" and mode="append" work but mode="before" and
mode="after" don't work for me.

What is the recommended way to insert an element between two other
elements without the before and after support? Should I find the first
and replace it whole clothe (not using "content") with explicit
"element" statements and then just insert the next element after that?

given source:

<container>
  <box width="10" height="8">
    <contents>stuff</contents>
  </box>
  <envelope lickable="yes">
    <weight>stuff</weights>
  </envelope>
</container>

and wanting to add a tape element between box and envelope should I:

<xsl:template mode=content" match="box">
  <xsl:element name="box">
    </xsl:attribute name="width">10</xsl:attribute>
    </xsl:attribute name="height">8</xsl:attribute>
  </xsl:element>
  <xsl:element name="tape>
  </xsl:element>
</xsl:template>

or is there a better way of doing it? One concern is that using the
above I'm nuking whatever was in box to start with.


Thanks!


On Mon, Sep 29, 2008 at 5:57 PM, Evan Lenz <evan@xxxxxxxxxxxx> wrote:
> I like to be as surgical as possible in my incremental transforms,
> especially when I've got a lot of things to update. In this case, I might
> use different modes, such as "content" and "append", as shown below:
>
> <xsl:stylesheet version="1.0"
>  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>  xmlns:client="http://somecompany.com/box/client";
>  xmlns:box="http://somecompany.com/box";
>  exclude-result-prefixes="client">
>
> <!-- BUSINESS LOGIC: -->
>  <!-- Set the value for all <box:rotation-time> elements -->
>  <xsl:template mode="content"
> match="box:rotation-time">newvalue</xsl:template>
>
>  <!-- Append a <box:work-manager> element to the end of <work-managers>
> content -->
>  <xsl:template mode="append" match="client:work-managers">
>   <box:work-manager>
>     <!-- etc. -->
>   </box:work-manager>
>  </xsl:template>
>
>
> <!-- GENERIC UTILITY CODE: -->
>  <!-- Identity transform for attributes, elements, comments, text, and PIs
> -->
>  <xsl:template match="@* | node()">
>   <xsl:copy>
>     <!-- Everything here (inside <xsl:copy>) only applies to elements -->
>     <xsl:apply-templates select="@*"/>
>     <xsl:apply-templates mode="content" select="."/>
>     <xsl:apply-templates mode="append" select="."/>
>   </xsl:copy>
>  </xsl:template>
>
>         <!-- By default, just process the existing content -->
>         <xsl:template mode="content" match="*">
>           <xsl:apply-templates/>
>         </xsl:template>
>
>         <!-- By default, don't append anything -->
>         <xsl:template mode="append" match="*"/>
>
> </xsl:stylesheet>
>
> In other cases, I've also used "insert" (insert before existing content),
> "before" (insert before the element itself), "after" (insert after the
> element), and "att-value" (for updating just the attribute value, without
> having to explicitly create a new attribute using <xsl:attribute> every
> time).
>
> Having such surgical precision can be very satisfying, but I don't usually
> bother if there are only one or two things to update (as in this example).
> But I thought I'd throw the idea out there anyway, in case you have lots of
> things to update or you anticipate adding more update rules.
>
> Evan
>
>
> Wendell Piez wrote:
>>
>> Paul,
>>
>> At 03:44 PM 9/29/2008, you wrote:
>>>
>>> What would be the best way to actually take the input xml transform it
>>> into a new xml and just change a value or add a new element?
>>
>> The best approach is to adapt the "identity transform", amending it with a
>> bit of extra logic to effect the changes you want.
>>
>> This is a well-documented approach, once you know the keywords. As you
>> might imagine, an identity transform is one in which the output replicates
>> the input. Strictly speaking, what you are trying to write might be called a
>> "near-identity transform" -- this might be as simple as adding a template.
>>
>>> Would it be best to do a template match on "/" and do a for-each on
>>> each element and then test each element to see if it was the one I
>>> wanted to change?
>>
>> No. It would be best to use template matching, as the standard identity
>> transform does. Its operation is fairly simple and straightforward, albeit
>> obscure if you don't know how XSLT templates work. But by the same token,
>> it's an excellent lesson in templates, which is indispensable for anyone
>> working with XSLT, and something you're much better off getting sooner
>> rather than later.
>>
>> Use your favorite search engine to find writeups and you should be set.
>> Ask back here if what you find isn't enough.
>>
>>> Would it be better to set up specify template match statements for
>>> each of the top-level elements and output the xml from the input
>>> document except in the case where I need to change it?
>>
>> Kind of ... the identity template (the heart of the logic) simply copies
>> input to output. Then, yes, you add templates to catch the cases where you
>> want to do something differently, like add or change or remove something. I
>> say "kind of" since the template matches all nodes, not just nodes at the
>> top level.
>>
>> Cheers,
>> Wendell
>>
>>
>> ======================================================================
>> Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
>> Mulberry Technologies, Inc.                http://www.mulberrytech.com
>> 17 West Jefferson Street                    Direct Phone: 301/315-9635
>> Suite 207                                          Phone: 301/315-9631
>> Rockville, MD  20850                                 Fax: 301/315-8285
>> ----------------------------------------------------------------------
>>  Mulberry Technologies: A Consultancy Specializing in SGML and XML
>> ======================================================================

Current Thread