[xsl] how to handle Attributes

Subject: [xsl] how to handle Attributes
From: "Joga Singh Rawat" <jrawat@xxxxxxxxxxxxxx>
Date: Thu, 19 Apr 2012 13:24:14 +0530
Hi All,
I need a help regarding attribute handling. We have made a function which is
working as follows:

Input XML
<JWSART copyright="yes" id="myid" dtdver="3.4">

Current Output
<html title="copyright:yes|id:myid|dtdver:3.4">

XSLT
<xsl:template match="JWSART">
 <html>
   <xsl:call-template name="collate-attributes">
    <xsl:with-param name="attribute-names">
    <xsl:text>copyright,id,dtdver</xsl:text>
    </xsl:with-param>
   </xsl:call-template>
</xsl:template>

<xsl:template name="collate-attributes">
  <xsl:param name="attribute-names" as="xsd:string"/>
  <!-- Condition will be true if it comes across an attribute name which has
been listed above  -->
  <xsl:if test="@*[name()=tokenize($attribute-names,',')]">
   <!-- This variable will contain all the available attribute names and
their corresponding values -->
   <xsl:variable name="attribute-names-and-values">
    <xsl:for-each select="@*[name()=tokenize($attribute-names,',')]">
     <xsl:sort select="name(.)" order="ascending"/>
     <xsl:value-of select="name(.)"/>
     <xsl:text>=</xsl:text>
     <xsl:value-of select="current()"/>
     <xsl:text>,</xsl:text>
    </xsl:for-each>
   </xsl:variable>
   <xsl:attribute name="title">
    <!-- Processing each of the attributes listed above -->
    <xsl:for-each select="tokenize($attribute-names,',')">
     <xsl:if test="contains($attribute-names-and-values,current()) and
not(substring-before(substring-after($attribute-names-and-values,current()),
'=')) ">
      <!-- Display attribute name -->
      <xsl:value-of select="current()"/>
      <xsl:text>:</xsl:text>
      <!-- Display attribute value contained in the variable -->
      <xsl:value-of
select="substring-before(substring-after($attribute-names-and-values,concat(
current(),'=')),',')"/>
      <xsl:if test="not(position()=last())">
       <xsl:choose>
        <!-- Call the template avoid-multiple-pipes if there are multiple
attribute names ahead -->
        <xsl:when
test="contains(substring-after($attribute-names,concat(current(),',')),',')"
>
         <xsl:call-template name="avoid-multiple-pipes">
          <xsl:with-param name="following-attribute-name">
           <xsl:value-of
select="substring-after($attribute-names,concat(current(),','))"/>
          </xsl:with-param>
          <xsl:with-param name="attribute-names-and-values">
           <xsl:value-of select="$attribute-names-and-values"/>
          </xsl:with-param>
         </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
         <xsl:if
test="contains($attribute-names-and-values,substring-after($attribute-names,
concat(current(),',')))">
          <xsl:text>|</xsl:text>
         </xsl:if>
        </xsl:otherwise>
       </xsl:choose>
      </xsl:if>
     </xsl:if>
    </xsl:for-each>
   </xsl:attribute>
  </xsl:if>
</xsl:template>

<xsl:template name="avoid-multiple-pipes">
 <xsl:param name="following-attribute-name" as="xsd:string"/>
 <xsl:param name="attribute-names-and-values" as="xsd:string"/>
 <!-- Pick attribute names one by one -->
 <xsl:variable name="next-attribute-name">
  <xsl:if test="contains($following-attribute-name,',')">
   <xsl:value-of select="substring-before($following-attribute-name,',')"/>
  </xsl:if>
  <xsl:if test="not(contains($following-attribute-name,','))">
   <xsl:value-of select="$following-attribute-name"/>
  </xsl:if>
 </xsl:variable>
 <xsl:choose>
  <!-- Publish | if the next listed attribute is present -->
  <xsl:when
test="contains($attribute-names-and-values,$next-attribute-name)">
   <xsl:text>|</xsl:text>
  </xsl:when>
  <xsl:otherwise>
   <!-- Keep checking until you come across an attribute which is available
-->
   <xsl:if test="contains($following-attribute-name,',')">
    <xsl:call-template name="avoid-multiple-pipes">
     <xsl:with-param name="following-attribute-name">
      <xsl:value-of
select="substring-after($following-attribute-name,concat($next-attribute-nam
e,','))"/>
     </xsl:with-param>
     <xsl:with-param name="attribute-names-and-values">
      <xsl:value-of select="$attribute-names-and-values"/>
     </xsl:with-param>
    </xsl:call-template>
   </xsl:if>
  </xsl:otherwise>
 </xsl:choose>
</xsl:template>


Now I want to change the desired output

New Output
<html title="copyright:yes;no;xx;yy|id:myid|dtdver:3.4;3.5">


To achieve the above result, I want to pass the parameters as follows:

<xsl:template match="JWSART">
 <html>
   <xsl:call-template name="collate-attributes">
    <xsl:with-param name="attribute-names">
    <xsl:text>copyright;no;xx;yy,id,dtdver;3.5</xsl:text>
    </xsl:with-param>
   </xsl:call-template>
</xsl:template>


Please suggest how to modify functions "collate attribute" to get the new
output.

Thanks

.JSR

Current Thread