tags:

views:

40

answers:

3

Hi all:

I'm having trouble inserting a block of text when a certain condition is met into an xml document using XSLT. Suppose I have the following xml:

<oldStep Name="Step1">
    <oldItems>
        <oldItem ItemName="item1">
        </oldItem>
        <!-- want to add an extra <Item> here if Step Name == "Step1" -->
        <oldItem ItemName="Step1item">
        </oldItem>
    </oldItems>
</oldStep>
<oldStep Name="Step2">
    <oldItems>
       ...
    </oldItems>
</oldStep>

Amongst the conversion of the old node names into new ones, I want to add an extra block of text (or a manually constructed node) whenever oldStep Name is equal to a certain value (in this case, Step1). I tried using the following XSLT, but it ended up with a weird behaviour in adding the block of text to every single node (sometimes even not under a node) in the xml once its matched. Also, I'm having trouble skipping the node so the node can be inserted within Items, not directly under oldStep:

<xsl:template match="oldItems">
    <xsl:element name="Item">
        <xsl:if test="../@Name = 'Step1'>
            <xsl:call-template name = "identity"></xsl:call-template>
        </xsl:if>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="node()" name="identity">
    <xsl:element name="Item">
        <xsl:attribute name="ItemName">Step1item</xsl:attribute>
        </xsl:apply-templates />
    </xsl:element>
</xsl:template>

I get the feeling that I've gotten the conditions wrong, but googling didn't really help (search string too vague). What am I missing in the xsl? Or, is there a better approach to this problem?

Thanks.

+1  A: 

This transformation:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*" name="identity">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="oldStep[@Name='Step1']/*/oldItem[1]">
  <xsl:call-template name="identity"/>

  <Item ItemName='Step1item'/>
 </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<steps>
    <oldStep Name="Step1">
        <oldItems>
            <oldItem ItemName="item1"/>
            <!-- want to add an extra <Item> here if Step Name == "Step1" -->
            <oldItem ItemName="Step1item"/>
        </oldItems>
    </oldStep>
    <oldStep Name="Step2">
        <oldItems>
       ...
        </oldItems>
    </oldStep>
</steps>

produces the wanted result:

<steps>
   <oldStep Name="Step1">
      <oldItems>
         <oldItem ItemName="item1"/>
         <Item ItemName="Step1item"/><!-- want to add an extra <Item> here if Step Name == "Step1" -->
         <oldItem ItemName="Step1item"/>
      </oldItems>
   </oldStep>
   <oldStep Name="Step2">
      <oldItems>
       ...
        </oldItems>
   </oldStep>
</steps>
Dimitre Novatchev
+1  A: 

Your template named "identity" matches any node, so will apply it for every node it processes. Don't have it match anything.

Paul Clapham
+1  A: 
Owen S.
@Owen S.: yeah I was still working on it after I made this post. I got close to what you have. I had an extra apply-template in the add-new-step1-stuff, and another apply-template was at the wrong place, so things looked a bit weird in a 5 digit xml file. Strangely I didn't use the <xsl:template match="@*|node()"> and still got it to work.
BeraCim