tags:

views:

51

answers:

2

Hi friends, in my xml file elements are not constant like say my file is

<alpha>
  <a>...</a>
  <b>...</b>
  <c>...</c>
</alpha>
<alpha>
  <a>...</a>
  <c>...</c>
</alpha>
<alpha>
  <a>...</a>
  <b>...</b>
</alpha>
<alpha>
  <a>...</a>
  <b>...</b>
  <c>...</c>
</alpha>

I meant to say i want to maintain all elements in my xml file by creating the non existing element in the set and should skip if any of the element is existed using xslt. Pls. help me to solve this problem.

Want OutPut Like as below for non existing elements with value 0 by creating in xslt.

**

<alpha>
      <a>...</a>
      <b>...</b>
      <c>...</c>
    </alpha>
    <alpha>
      <a>...</a>
      <b>0</b>
      <c>...</c>
    </alpha>
    <alpha>
      <a>...</a>
      <b>...</b>
      <c>0</c>
    </alpha>
    <alpha>
      <a>...</a>
      <b>...</b>
      <c>...</c>
    </alpha>

**

+1  A: 

XSLT 2.0

    <xsl:template match="a|b|c">
     <xsl:copy-of select="."/>
    </xsl:template>
    <xsl:template match="alpha">
     <xsl:variable name="alpha" select="."/>
     <xsl:variable name="forced">
      <forced>
       <a>0</a>
       <b>0</b>
       <c>0</c>
      </forced>
     </xsl:variable>
     <xsl:copy>
      <xsl:for-each select="$forced/forced/*">
       <xsl:variable name="current" select="name()"/>
       <xsl:choose>
        <xsl:when test="exists($alpha/*[name() = $current])">
         <xsl:apply-templates select="$alpha/*[name() = $current]"/>
        </xsl:when>
        <xsl:otherwise>
         <xsl:apply-templates select="$forced/forced/*[name() = $current]"/>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:for-each>
     </xsl:copy>
    </xsl:template>

XSLT 1.0

<xsl:template match="/root">
 <root>
  <xsl:for-each select="alpha">
          <alpha>
    <xsl:choose>
     <xsl:when test="a">
      <xsl:copy-of select="a"/>
     </xsl:when>
     <xsl:otherwise>
      <a>0</a>
     </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
     <xsl:when test="b">
      <xsl:copy-of select="b"/>
     </xsl:when>
     <xsl:otherwise>
      <b>0</b>
     </xsl:otherwise>
    </xsl:choose>
    <xsl:choose>
     <xsl:when test="c">
      <xsl:copy-of select="c"/>
     </xsl:when>
     <xsl:otherwise>
      <c>0</c>
     </xsl:otherwise>
    </xsl:choose>
          </alpha>
         </xsl:for-each>
 </root>
</xsl:template>
Peter Lindqvist
It won't work with XSLT 1.0; your variable $forced is a RTF (Result Tree Fragment), and you can't use RTF within a XPath expression.
Erlock
Very well, i added a 1.0 template as well. Not that i'm very fond of it. I always use saxon for processing and 2.0 is so much better.
Peter Lindqvist
Thanks a lot, I got the solution.
naidu
+1  A: 

A simple, slightly modified identity transformation can do this:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
      <xsl:if test="self::alpha">
        <xsl:if test="not(a)"><a>0</a></xsl:if>
        <xsl:if test="not(b)"><b>0</b></xsl:if>
        <xsl:if test="not(c)"><c>0</c></xsl:if>
      </xsl:if>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

Be aware that the above does not create the a, b, c elements in this particular order (since I don't think this is really necessary). It merely makes sure that all three of them are there, and copies the rest of the input as it is.

Tomalak