MINI MINI MANI MO

Path : /opt/oracle/product/18c/dbhomeXE/rdbms/xml/xsl/
File Upload :
Current File : //opt/oracle/product/18c/dbhomeXE/rdbms/xml/xsl/kuaview.xsl

<?xml version="1.0"?>
<!--

 Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.

NAME
    kuaview.xsl
DESCRIPTION
    Convert sxml VIEW diff document to ALTER_XML document

    MODIFIED        MM/DD/YY
    tbhukya     03/15/15 - Proj 47173: Data bound collation
    sogugupt    12/05/14 - Bug 18596422: illegal name attribute value in xsl
    rapayne     01/20/13 - bug 15917102: add not-alterable support for 
                                        (12.1)BEQUEATH clause diffs.
                                       Also, add support EDITIONABLE diffs.
    rapayne     07/27/12 - bug 12702319: add support for alter constraints.
    lbarton     07/24/09 - bug 8342311: view subquery restriction clause
    rapayne     06/09/06 - Initial version
 -->
<xsl:stylesheet version="1.0" xmlns:sxml="http://xmlns.oracle.com/ku" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <!-- Top level imports -->
 <xsl:import href="kuacomm.xsl"/>
 <!-- Templates -->
 <xsl:template match="sxml:VIEW">
  <!-- *******************************************************************
Template: VIEW - top-level template for views.
******************************************************************** -->
  <xsl:element name="ALTER_XML" namespace="http://xmlns.oracle.com/ku">
   <xsl:attribute name="version">1.0</xsl:attribute>
   <!-- Object type -->
   <xsl:element name="OBJECT_TYPE">VIEW</xsl:element>
   <!-- Display schema.objname for CoMPareObjects 1 and 2  -->
   <xsl:call-template name="CmpObjects">
    <xsl:with-param name="ParentNode" select="."/>
   </xsl:call-template>
   <!-- Alter list -->
   <xsl:variable name="viewNode" select="."/>
   <xsl:element name="ALTER_LIST">
    <!--check non-alterable view attributes  -->
    <xsl:call-template name="checkAlterable">
     <xsl:with-param name="ParentNode" select="."/>
    </xsl:call-template>
    <!--check if view is editionable  -->
    <xsl:call-template name="checkEditionable">
     <xsl:with-param name="ParentNode" select="."/>
    </xsl:call-template>
    <!--check for restriction changes -->
    <xsl:call-template name="checkRestriction">
     <xsl:with-param name="ParentNode" select="."/>
    </xsl:call-template>
    <!--check for UNIQUE constraint changes -->
    <xsl:for-each select=".//sxml:UNIQUE_KEY_CONSTRAINT_LIST[@src]/sxml:UNIQUE_KEY_CONSTRAINT_LIST_ITEM[*]">
     <xsl:call-template name="doConstraint">
      <xsl:with-param name="ParentNode" select="$viewNode"/>
      <xsl:with-param name="ConstraintNode" select="."/>
      <xsl:with-param name="Type">UNIQUE</xsl:with-param>
     </xsl:call-template>
    </xsl:for-each>
    <!--check for PRIMARY KEY constraint changes -->
    <xsl:for-each select=".//sxml:PRIMARY_KEY_CONSTRAINT_LIST[@src]/sxml:PRIMARY_KEY_CONSTRAINT_LIST_ITEM[*]">
     <xsl:call-template name="doConstraint">
      <xsl:with-param name="ParentNode" select="$viewNode"/>
      <xsl:with-param name="ConstraintNode" select="."/>
      <xsl:with-param name="Type">PRIMARY KEY</xsl:with-param>
     </xsl:call-template>
    </xsl:for-each>
    <!--check for FOREIGN KEY constraint changes -->
    <xsl:for-each select=".//sxml:FOREIGN_KEY_CONSTRAINT_LIST[@src]/sxml:FOREIGN_KEY_CONSTRAINT_LIST_ITEM[*]">
     <xsl:call-template name="doConstraint">
      <xsl:with-param name="ParentNode" select="$viewNode"/>
      <xsl:with-param name="ConstraintNode" select="."/>
      <xsl:with-param name="Type">FOREIGN KEY</xsl:with-param>
     </xsl:call-template>
    </xsl:for-each>
    <!-- view name rename (the last thing we do) -->
    <xsl:call-template name="RenameView">
     <xsl:with-param name="ParentNode" select="."/>
    </xsl:call-template>
   </xsl:element>
  </xsl:element>
 </xsl:template>
 <xsl:template name="checkAlterable">
  <xsl:param name="ParentNode" select="''"/>
  <!-- *******************************************************************
Template: checkAlterable - Detects certain non-alterable cases
 1. View NAME change
 2. COL_LIST diffs
 3. SUBQUERY diffs
 4. BEQUEATH diffs
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
 Action = "PARSE"
******************************************************************** -->
  <!-- Check for COL_LIST  difference -->
  <xsl:for-each select="$ParentNode/sxml:COL_LIST/sxml:COL_LIST_ITEM">
   <xsl:if test="./@src or sxml:NAME/@value1">
    <xsl:call-template name="CommonNotAlterable">
     <xsl:with-param name="XpathNode" select="."/>
     <xsl:with-param name="NameNode">
      <xsl:choose>
       <xsl:when test="sxml:NAME/@value1">
        <xsl:value-of select="sxml:NAME/@value1"/>
       </xsl:when>
       <xsl:otherwise>
        <xsl:value-of select="sxml:NAME"/>
       </xsl:otherwise>
      </xsl:choose>
     </xsl:with-param>
     <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
     <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
     <xsl:with-param name="Subst">COLUMN LIST</xsl:with-param>
    </xsl:call-template>
   </xsl:if>
  </xsl:for-each>
  <!-- Check for DEFAULT_COLLATION -->
  <xsl:if test="$ParentNode/sxml:DEFAULT_COLLATION/@value1">
   <xsl:call-template name="CommonNotAlterable">
    <xsl:with-param name="XpathNode" select="$ParentNode/sxml:DEFAULT_COLLATION"/>
    <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
    <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
    <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
    <xsl:with-param name="Subst">DEFAULT_COLLATION</xsl:with-param>
   </xsl:call-template>
  </xsl:if>
  <!-- Check for BEQUEATH differences -->
  <xsl:if test="$ParentNode/sxml:BEQUEATH/@value1 or $ParentNode/sxml:BEQUEATH/@src">
   <xsl:call-template name="CommonNotAlterable">
    <xsl:with-param name="XpathNode" select="$ParentNode/sxml:BEQUEATH"/>
    <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
    <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
    <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
    <xsl:with-param name="Subst">BEQUEATH</xsl:with-param>
   </xsl:call-template>
  </xsl:if>
  <!-- Check for SUBQUERY differences -->
  <xsl:if test="$ParentNode/sxml:SUBQUERY/@value1">
   <xsl:call-template name="CommonNotAlterable">
    <xsl:with-param name="XpathNode" select="$ParentNode/sxml:SUBQUERY"/>
    <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
    <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
    <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
    <xsl:with-param name="Subst">SUBQUERY</xsl:with-param>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>
 <xsl:template name="checkEditionable">
  <xsl:param name="ParentNode" select="''"/>
  <!-- *******************************************************************
Template: checkEditionable - process diffs in EDITIONABLE attribute.
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
 Action = "PARSE" or "SQL"
Note: we are here if there are diffs on the EDITIONABLE node.
      Aldo, EDITIONABLE is the default attribute.
******************************************************************** -->
  <xsl:if test="sxml:NONEDITIONABLE/@src">
   <xsl:element name="ALTER_LIST_ITEM">
    <xsl:call-template name="doEditionable">
     <xsl:with-param name="ParentNode" select="$ParentNode"/>
     <xsl:with-param name="Action">PARSE</xsl:with-param>
    </xsl:call-template>
    <xsl:call-template name="doEditionable">
     <xsl:with-param name="ParentNode" select="$ParentNode"/>
     <xsl:with-param name="Action">SQL</xsl:with-param>
    </xsl:call-template>
   </xsl:element>
  </xsl:if>
 </xsl:template>
 <xsl:template name="doEditionable">
  <xsl:param name="ParentNode" select="''"/>
  <xsl:param name="Action" select="''"/>
  <!-- *******************************************************************
Template: doEditionable - process diffs in EDITIONABLE attribute.
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
 Action = "PARSE" or "SQL"
Note: we are here if there are diffs on the EDITIONABLE node.
      Aldo, EDITIONABLE is the default attribute.
******************************************************************** -->
  <xsl:choose>
   <xsl:when test="$Action='PARSE' and ($PRS_NAME=1 or 
                                        $PRS_CLAUSE_TYPE=1 or
                                        $PRS_XPATH=1)">
    <xsl:element name="PARSE_LIST">
     <xsl:call-template name="AddXPathParseItem">
      <xsl:with-param name="Node" select="./sxml:EDITIONABLE"/>
     </xsl:call-template>
     <xsl:call-template name="AddParseItem">
      <xsl:with-param name="ParseIt" select="$PRS_NAME"/>
      <xsl:with-param name="Item">NAME</xsl:with-param>
      <xsl:with-param name="Value1" select="$ParentNode/sxml:NAME"/>
     </xsl:call-template>
     <xsl:call-template name="AddParseItem">
      <xsl:with-param name="ParseIt" select="$PRS_CLAUSE_TYPE"/>
      <xsl:with-param name="Item">CLAUSE_TYPE</xsl:with-param>
      <xsl:with-param name="Value1">EDITIONABLE</xsl:with-param>
     </xsl:call-template>
    </xsl:element>
   </xsl:when>
   <xsl:when test="$Action='SQL'">
    <xsl:element name="SQL_LIST">
     <xsl:element name="SQL_LIST_ITEM">
      <xsl:element name="TEXT">
       <xsl:text>ALTER VIEW </xsl:text>
       <xsl:call-template name="SchemaName">
        <xsl:with-param name="ParentNode" select="$ParentNode"/>
       </xsl:call-template>
       <xsl:choose>
        <xsl:when test="./sxml:NONEDITIONABLE[@src='1']"> EDITIONABLE </xsl:when>
        <xsl:otherwise> NONEDITIONABLE</xsl:otherwise>
       </xsl:choose>
      </xsl:element>
     </xsl:element>
    </xsl:element>
   </xsl:when>
  </xsl:choose>
 </xsl:template>
 <xsl:template name="doConstraint">
  <xsl:param name="ParentNode" select="''"/>
  <xsl:param name="ConstraintNode" select="''"/>
  <xsl:param name="Type" select="''"/>
  <!-- *******************************************************************
Template: doConstraint - 
       
Parameters:
 ParentNode       - VIEW node
 constraintNode - 
 Type                 - UNIQUE || FOREIGN || CHECK
******************************************************************** -->
  <xsl:choose>
   <xsl:when test="./parent::node()/@src='1' or ./@src='1'">
    <!--                          Drop  Constraints                              -->
    <!-- get all constraint nodes that need to be dropped -->
    <xsl:call-template name="AddDropConstraint">
     <xsl:with-param name="ParentNode" select="$ParentNode"/>
     <xsl:with-param name="ConstraintNode" select="."/>
     <xsl:with-param name="Type" select="'$Type'"/>
     <xsl:with-param name="action">DROP</xsl:with-param>
    </xsl:call-template>
   </xsl:when>
   <!--                          Add  Constraints                              -->
   <!-- get all constraint nodes that need to be dropped -->
   <xsl:when test="./parent::node()/@src='2' or ./@src='2'">
    <xsl:call-template name="AddDropConstraint">
     <xsl:with-param name="ParentNode" select="$ParentNode"/>
     <xsl:with-param name="ConstraintNode" select="."/>
     <xsl:with-param name="Type" select="$Type"/>
     <xsl:with-param name="action">ADD</xsl:with-param>
    </xsl:call-template>
   </xsl:when>
  </xsl:choose>
 </xsl:template>
 <xsl:template name="AddDropConstraint">
  <xsl:param name="ParentNode" select="''"/>
  <xsl:param name="ConstraintNode" select="''"/>
  <xsl:param name="Type" select="''"/>
  <xsl:param name="action" select="''"/>
  <!-- *******************************************************************
Template: AddDropContraint - both INLINE and OUT_OF_LINE constraints.
       In general inline constraints do NOT have column lists.
Parameters:
 ParentNode       - top-level VIEW node
 constraintNode - constraint node to add/drop
 Type                   - UNIQUE || PRIMARY || CHECK
 action                - 'ADD' || 'DROP'
******************************************************************** -->
  <xsl:element name="ALTER_LIST_ITEM">
   <xsl:if test="$PRS_NAME=1 or 
                  $PRS_CLAUSE_TYPE=1 or
                  $PRS_XPATH=1">
    <xsl:element name="PARSE_LIST">
     <xsl:call-template name="AddXPathParseItem">
      <xsl:with-param name="Node" select="$ParentNode"/>
     </xsl:call-template>
     <xsl:call-template name="AddParseItem">
      <xsl:with-param name="ParseIt" select="$PRS_NAME"/>
      <xsl:with-param name="Item">NAME</xsl:with-param>
      <xsl:with-param name="Value1" select="$ParentNode/sxml:NAME/@value1"/>
     </xsl:call-template>
     <xsl:call-template name="AddParseItem">
      <xsl:with-param name="ParseIt" select="$PRS_CLAUSE_TYPE"/>
      <xsl:with-param name="Item">CLAUSE_TYPE</xsl:with-param>
      <xsl:with-param name="Value1" select="$action"/>
     </xsl:call-template>
    </xsl:element>
   </xsl:if>
   <xsl:element name="SQL_LIST">
    <xsl:element name="SQL_LIST_ITEM">
     <xsl:element name="TEXT">
      <xsl:text>ALTER VIEW </xsl:text>
      <xsl:call-template name="SchemaName">
       <xsl:with-param name="ParentNode" select="$ParentNode"/>
      </xsl:call-template>
      <xsl:text> </xsl:text>
      <xsl:value-of select="$action"/>
      <xsl:text> CONSTRAINT </xsl:text>
      <xsl:call-template name="QuotedName">
       <xsl:with-param name="NameNode" select="sxml:NAME"/>
      </xsl:call-template>
      <xsl:if test="$action = 'ADD'">
       <xsl:text> </xsl:text>
       <xsl:value-of select="$Type"/>
       <!-- get column list -->
       <xsl:call-template name="generateColList">
        <xsl:with-param name="ColList" select="sxml:COL_LIST"/>
       </xsl:call-template>
       <xsl:if test="$Type = 'FOREIGN KEY'">
        <xsl:text> REFERENCES </xsl:text>
        <xsl:call-template name="SchemaName">
         <xsl:with-param name="ParentNode" select="./sxml:REFERENCES"/>
        </xsl:call-template>
        <xsl:call-template name="generateColList">
         <xsl:with-param name="ColList" select="./sxml:REFERENCES/sxml:COL_LIST"/>
        </xsl:call-template>
       </xsl:if>
       <!-- generate DISABLE if appropriate -->
       <xsl:if test="./sxml:DISABLE">
        <xsl:text> DISABLE</xsl:text>
       </xsl:if>
      </xsl:if>
     </xsl:element>
    </xsl:element>
   </xsl:element>
  </xsl:element>
 </xsl:template>
 <xsl:template name="checkRestriction">
  <xsl:param name="ParentNode" select="''"/>
  <!-- *******************************************************************
Template: checkRestriction - look for diffs in RESTRICTION
       The only valid case is altering to/from read_only for an editioning view
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
******************************************************************** -->
  <xsl:if test="$ParentNode/sxml:RESTRICTION//@src">
   <xsl:choose>
    <xsl:when test="($ParentNode/sxml:RESTRICTION[@src]/sxml:READ_ONLY or $ParentNode/sxml:RESTRICTION/sxml:READ_ONLY/@src) and not ($ParentNode/sxml:RESTRICTION/sxml:CHECK_OPTION)">
     <xsl:call-template name="checkReadOnly">
      <xsl:with-param name="ParentNode" select="$ParentNode"/>
     </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
     <xsl:call-template name="CommonNotAlterable">
      <xsl:with-param name="XpathNode" select="$ParentNode/sxml:RESTRICTION"/>
      <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
      <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
      <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
      <xsl:with-param name="Subst">RESTRICTION</xsl:with-param>
     </xsl:call-template>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:if>
 </xsl:template>
 <xsl:template name="checkReadOnly">
  <xsl:param name="ParentNode" select="''"/>
  <!-- *******************************************************************
Template: checkReadOnly- 
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
******************************************************************** -->
  <xsl:if test="$ParentNode/sxml:RESTRICTION/@src or 
                $ParentNode/sxml:RESTRICTION/sxml:READ_ONLY/@src">
   <xsl:choose>
    <xsl:when test="$ParentNode/sxml:EDITIONING_VIEW">
     <xsl:element name="ALTER_LIST_ITEM">
      <xsl:call-template name="alterReadOnlyView">
       <xsl:with-param name="ParentNode" select="$ParentNode"/>
       <xsl:with-param name="Action">PARSE</xsl:with-param>
      </xsl:call-template>
      <xsl:call-template name="alterReadOnlyView">
       <xsl:with-param name="ParentNode" select="$ParentNode"/>
       <xsl:with-param name="Action">SQL</xsl:with-param>
      </xsl:call-template>
     </xsl:element>
    </xsl:when>
    <xsl:otherwise>
     <xsl:call-template name="CommonNotAlterable">
      <xsl:with-param name="XpathNode" select="$ParentNode/sxml:RESTRICTION"/>
      <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
      <xsl:with-param name="Reason">VIEW_ATTRIBUTE</xsl:with-param>
      <xsl:with-param name="Message" select="$MSG_VIEW_ATTRIBUTE"/>
      <xsl:with-param name="Subst">NOT EDITIONING VIEW</xsl:with-param>
     </xsl:call-template>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:if>
 </xsl:template>
 <xsl:template name="alterReadOnlyView">
  <xsl:param name="ParentNode" select="''"/>
  <xsl:param name="Action" select="''"/>
  <!-- *******************************************************************
Template: alterReadOnlyView - only possible to alter EDITIONING VIEWS. 
      If READ_ONLY has been alter and not an editioning view then only
      a not alterable parse item is generated.
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
 Action - PARSE or SQL
******************************************************************** -->
  <xsl:choose>
   <xsl:when test="$Action='PARSE' and ($PRS_NAME=1 or 
                                        $PRS_CLAUSE_TYPE=1 or
                                        $PRS_XPATH=1)">
    <xsl:element name="PARSE_LIST">
     <xsl:call-template name="AddXPathParseItem">
      <xsl:with-param name="Node" select="./sxml:RESTRICTION/sxml:READ_ONLY"/>
     </xsl:call-template>
     <xsl:choose>
      <xsl:when test="./sxml:RESTRICTION[@src='1']/sxml:READ_ONLY or ./sxml:RESTRICTION/sxml:READ_ONLY/@src='1'">
       <xsl:call-template name="AddParseItem">
        <xsl:with-param name="ParseIt" select="$PRS_CLAUSE_TYPE"/>
        <xsl:with-param name="Item">CLAUSE_TYPE</xsl:with-param>
        <xsl:with-param name="Value1">READ_WRITE</xsl:with-param>
       </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
       <xsl:call-template name="AddParseItem">
        <xsl:with-param name="ParseIt" select="$PRS_CLAUSE_TYPE"/>
        <xsl:with-param name="Item">CLAUSE_TYPE</xsl:with-param>
        <xsl:with-param name="Value1">READ_ONLY</xsl:with-param>
       </xsl:call-template>
      </xsl:otherwise>
     </xsl:choose>
    </xsl:element>
   </xsl:when>
   <xsl:when test="$Action='SQL'">
    <xsl:element name="SQL_LIST">
     <xsl:element name="SQL_LIST_ITEM">
      <xsl:element name="TEXT">
       <xsl:text>ALTER VIEW </xsl:text>
       <xsl:call-template name="SchemaName">
        <xsl:with-param name="ParentNode" select="$ParentNode"/>
       </xsl:call-template>
       <xsl:choose>
        <xsl:when test="./sxml:RESTRICTION[@src='1']/sxml:READ_ONLY or ./sxml:RESTRICTION/sxml:READ_ONLY/@src='1'"> READ WRITE </xsl:when>
        <xsl:otherwise> READ ONLY</xsl:otherwise>
       </xsl:choose>
      </xsl:element>
     </xsl:element>
    </xsl:element>
   </xsl:when>
  </xsl:choose>
 </xsl:template>
 <xsl:template name="RenameView">
  <xsl:param name="ParentNode" select="''"/>
  <!-- *******************************************************************
Template: RenameView
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
******************************************************************** -->
  <xsl:if test="$ParentNode/sxml:NAME/@value1">
   <xsl:element name="ALTER_LIST_ITEM">
    <xsl:if test="$PRS_NAME=1 or 
                  $PRS_CLAUSE_TYPE=1 or
                  $PRS_XPATH=1">
     <xsl:element name="PARSE_LIST">
      <xsl:call-template name="AddXPathParseItem">
       <xsl:with-param name="Node" select="$ParentNode"/>
      </xsl:call-template>
      <xsl:call-template name="AddParseItem">
       <xsl:with-param name="ParseIt" select="$PRS_NAME"/>
       <xsl:with-param name="Item">NAME</xsl:with-param>
       <xsl:with-param name="Value1" select="$ParentNode/sxml:NAME/@value1"/>
      </xsl:call-template>
      <xsl:call-template name="AddParseItem">
       <xsl:with-param name="ParseIt" select="$PRS_CLAUSE_TYPE"/>
       <xsl:with-param name="Item">CLAUSE_TYPE</xsl:with-param>
       <xsl:with-param name="Value1">RENAME_VIEW</xsl:with-param>
      </xsl:call-template>
     </xsl:element>
    </xsl:if>
    <xsl:element name="SQL_LIST">
     <xsl:element name="SQL_LIST_ITEM">
      <xsl:element name="TEXT">
       <xsl:text>RENAME </xsl:text>
       <xsl:call-template name="SourceName">
        <xsl:with-param name="NameNode" select="$ParentNode/sxml:NAME"/>
       </xsl:call-template>
       <xsl:text> TO </xsl:text>
       <xsl:call-template name="QuotedName">
        <xsl:with-param name="NameNode" select="sxml:NAME"/>
       </xsl:call-template>
      </xsl:element>
     </xsl:element>
    </xsl:element>
   </xsl:element>
  </xsl:if>
 </xsl:template>
 <xsl:template name="generateColList">
  <xsl:param name="ColList" select="''"/>
  <!-- *******************************************************************
Template: RenameView
Parameters:
 ParentNode - Parent node of SCHEMA, NAME
******************************************************************** -->
  <xsl:text>  (</xsl:text>
  <xsl:for-each select="$ColList/sxml:COL_LIST_ITEM">
   <xsl:value-of select="./sxml:NAME"/>
   <xsl:if test="(position()!=last())">
    <xsl:text>, </xsl:text>
   </xsl:if>
  </xsl:for-each>
  <xsl:text>)</xsl:text>
 </xsl:template>
</xsl:stylesheet>

OHA YOOOO