Subject: RE: [xsl] Maintaining XSL ... From: "Asit Kharshikar" <AsitK@xxxxxxxxxxxxxxx> Date: Tue, 9 Aug 2005 23:07:31 -0700 |
Hello Charles, I guess what you are saying is true. My stylesheet is not very well structured right now. I guess what I am looking for are guidelines for creating xsl stylesheets that are used for rendering forms. Basically in the field people are comfortable with creating html based forms and we need some kind of bridge between our XML data representation and html. We now use xsl to generate the html however we need to make it easy for people to edit and create their own forms. Maybe a third party xsl editor can be used if the xsl logic is segregated better. They should not be able to change the business logic i.e only work with the layout and validation rules tied to form elements. I have included a sample below Thanks Regards - Asit <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rqa="http://www.supportsoft.com/schemas/rqa" xmlns:si="http://www.supportsoft.com/schemas/smartissue" exclude-result-prefixes="xs xsi rqa"> <xsl:strip-space elements="*" /> <xsl:output method="html" version="4.0" encoding="UTF-8" indent="no"/> <!-- ASP Variables Init To be injected from ASP These variables are replaced dynamically if transformed on the server. --> <xsl:variable name="audience" select="'ux'"/> <xsl:variable name="issuestatus" select="'unknown'"/> <xsl:variable name="HiddenFieldsHtml" select="'unknown'"/> <!-- This variable indicates if attachments needs to be shown --> <xsl:variable name="displayAttachmentsBtn" select="'false'"/> <xsl:variable name="displayUpdateBtn" select="'false'"/> <xsl:variable name="displaySearchBtn" select="'false'"/> <xsl:variable name="displayReopenBtn" select="'false'"/> <xsl:variable name="displayBackBtn" select="'false'"/> <xsl:variable name="displayCreateNewRequestBtn" select="'false'"/> <xsl:variable name="displaySubmitBtn" select="'false'"/> <xsl:variable name="ReopenUrl" select="'unknown'"/> <xsl:variable name="BackUrl" select="'unknown'"/> <xsl:variable name="userLCID" select="'unknown'"/> <xsl:variable name="userTimeZone" select="'unknown'"/> <xsl:variable name="attachmentButtonTitle" select="'AttachmentsAttachments'"/> <xsl:variable name="kcsInstalled" select="'true'"/> <xsl:variable name="bForceKCSearch" select="'false'"/> <xsl:variable name="allowSubmissionChoice" select="'false'"/> <xsl:variable name="showToolTips" select="'false'"/> <xsl:variable name="xsdFormCSS" select="'/sdccommon/rrn/inc/xsdforms-requestassist_default.css'"/> <!-- ASP Variables Init To be injected from ASP --> <xsl:variable name="guidPrefix" select="'GUID_'"/> <xsl:variable name="instance" select="/" /> <xsl:variable name="noNamespaceSchemaLocation" select="normalize-space($instance/*/@xsi:noNamespaceSchemaLocation)" /> <xsl:variable name="schemaLocation" select="normalize-space($instance/*/@xsi:schemaLocation)" /> <xsl:param name="schemaDoc"> <xsl:call-template name="schemaLocation"> <xsl:with-param name="ns" select="namespace-uri($instance/*)" /> </xsl:call-template> </xsl:param> <xsl:variable name="schema" select="document($schemaDoc, $instance)" /> <xsl:variable name="issueNode" select="$schema/xs:schema/xs:annotation/xs:appinfo/*" /> <xsl:variable name="issueGuid" select="$schema/xs:schema/xs:annotation/xs:appinfo//rqa:sik_iss_guid/rqa :value" /> <xsl:variable name="selIssueType" select="$schema/xs:schema/xs:annotation/xs:appinfo//rqa:sik_iss_type/rqa :value" /> <!-- We don't process recursive Schema includes yet. Just the first level. --> <xsl:variable name="includedschemalocations" select="$schema/xs:schema/xs:include/@schemaLocation"/> <!-- Make a single document of all the inlcuded Schemas. --> <xsl:variable name="schemaFull" select="document($includedschemalocations) | $schema"/> <xsl:template name="schemaLocation"> <xsl:param name="ns"/> <xsl:choose> <xsl:when test="$ns"> <xsl:value-of select="substring-before(substring-after(concat(' ', $schemaLocation, ' '), concat(' ', $ns, ' ')), ' ')" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$noNamespaceSchemaLocation" /> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:variable name='formClassName'> <xsl:choose> <xsl:when test="$issueNode"> requestContainer </xsl:when> <xsl:otherwise> newRequestContainer </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- reusable replace-string function --> <!-- <xsl:template name="replace-string"> <xsl:param name="text"/> <xsl:param name="from"/> <xsl:param name="to"/> <xsl:choose> <xsl:when test="contains($text, $from)"> <xsl:variable name="before" select="substring-before($text, $from)"/> <xsl:variable name="after" select="substring-after($text, $from)"/> <xsl:variable name="prefix" select="concat($before, $to)"/> <xsl:value-of select="$before"/> <xsl:value-of select="$to"/> <xsl:call-template name="replace-string"> <xsl:with-param name="text" select="$after"/> <xsl:with-param name="from" select="$from"/> <xsl:with-param name="to" select="$to"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$text"/> </xsl:otherwise> </xsl:choose> </xsl:template> --> <xsl:template match="/"> <link type="text/css" rel="stylesheet"> <xsl:attribute name="href"><xsl:value-of select="$xsdFormCSS"/></xsl:attribute> </link> <div> <script language="javascript" type="text/javascript" src="/sdccommon/rrn/inc/requestform.js"></script> <script language="javascript" src="/sdccommon/rrn/inc/smartissue.js"></script> <script language="javascript" src="/sdccommon/rrn/inc/cal.js"/> <script language="javascript"> function sprt_clear_date_and_hidden(field) { if ( document.all("issueform")[field +"_Iso"].value == " " ) { g_property_changed = false; } else { g_property_changed = true; } document.all("issueform")[field].value = ""; document.all("issueform")[field +"_Iso"].value = ""; } </script> <script language="javascript"> function sprt_chkOnClick(id) { if (document.all("issueform")[id].checked == false) { document.all("issueform")[id].value="off"; } else { document.all("issueform")[id].value="on"; } } </script> <script language="javascript"> var classHTMLHeader = ""; var classHTMLBody = ""; var classHTMLFooter = ""; var classProps = new Array(); var defaultCollapsed = new Array(); var g_harvestInfo = new harvestInfo(); var g_smartValues = new Array(); var g_showToolTips = <xsl:value-of select="$showToolTips"/>; var g_bSmartIssueCreated = false; var parentITHTML = ""; </script> <table> <tr> <td> <form class="rrnIssuePage" method="POST" name="issueform" onSubmit="return validate_formdata(this);"> <xsl:attribute name="class">rrnIssuePage</xsl:attribute> <table class="requestTitleContainer"> <xsl:call-template name="formTitle"/> </table> <xsl:if test="$issueNode"> <xsl:variable name="printpageUrlAn"> <xsl:text>/sdchealtop/rrn/issuedetailsprint.asp?issueGuid=</xsl:text> </xsl:variable> <xsl:variable name="printpageUrlUx"> <xsl:text>/sdcxuser/rrn/issuedetailsprint.asp?issueGuid=</xsl:text> </xsl:variable> <xsl:choose> <xsl:when test="$audience='an'"> <div align='right'> <a target="new" align="right"> <xsl:attribute name="href"> <xsl:value-of select="$printpageUrlAn"/> <xsl:value-of select="$issueGuid"/> <xsl:text>&printer=true</xsl:text> </xsl:attribute> Printer Friendly Version </a> </div> </xsl:when> <xsl:otherwise> <div align='right'> <a target="new" align="right"> <xsl:attribute name="href"> <xsl:value-of select="$printpageUrlUx"/> <xsl:value-of select="$issueGuid"/> <xsl:text>&printer=true</xsl:text> </xsl:attribute> Printer Friendly Version </a> </div> </xsl:otherwise> </xsl:choose> </xsl:if> <table class="//{$formClassName}"> <!-- <xsl:call-template name="formHeader"/> --> <script language="javascript"> function onSelectIssueTypeParent(issType) { var f = document.issueform; if(issType != '') { //f["Kernel::Kernel::sik_iss_type"].innerHTML = "<option selected=\"selected\" value=\"" + issType + "\"/>"; var oOption = document.createElement("OPTION"); f["Kernel::Kernel::sik_iss_type"].options.add(oOption); oOption.value = issType; f["Kernel::Kernel::sik_iss_type"].value = issType; } else f["Kernel::Kernel::sik_iss_type"].value = ''; onSelectIssueType(); } function onSelectIssueType() { var f = document.issueform; <xsl:choose> <xsl:when test="$issueNode"> <xsl:choose> <xsl:when test="$audience='an'"> f["action_post"].value = "typeselected"; f.action='issuedetails.asp?issueguid=<xsl:value-of select="$issueGuid"/>'; </xsl:when> <xsl:otherwise> f["action_post"].value = "typeselected"; f.action='issueview.asp?issueguid=<xsl:value-of select="$issueGuid"/>'; </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> f.action="issue_new.asp"; </xsl:otherwise> </xsl:choose> f.submit(); } <xsl:apply-templates select="$schema/xs:schema/xs:element"> <xsl:with-param name="node" select="$issueNode" /> <xsl:with-param name="strHTMLID" select="generate-id()" /> <xsl:with-param name="toggleable" select="false()" /> </xsl:apply-templates> //document.write(classHTMLHeader); //document.write("<table class='issueTableStyle' ><tr><td>"); document.write(classHTMLBody + classHTMLFooter); //document.write('</td></tr></table>'); //dumpToFile( "C:\\issue.html", classHTMLHeader + classHTMLBody + classHTMLFooter); //alert(classHTMLHeader + classHTMLBody + classHTMLFooter); if(!g_bSmartIssueCreated) { createIssue("RequestAssist Harvest Issue"); g_bSmartIssueCreated=true; } var smartProp; var strProp; for(smartProp in g_smartValues) { strProp = smartProp.valueOf(); var val = getSmartVal(g_smartValues[strProp]); // alert(smartProp + " = " + g_smartValues[smartProp] + " = " + val); if(val != ""){ if (document.all[strProp]){ document.all[strProp].value = val; } else{ //Nagendra if (document.getElementById(strProp)){ document.getElementById(strProp).value = val; } } } } </script> </table> <xsl:if test="not($HiddenFieldsHtml='unknown')"> <xsl:value-of disable-output-escaping="yes" select="$HiddenFieldsHtml"/> </xsl:if> </form> </td> </tr> <tr> <td valign="top"> <div name="activityActions" id="activityActions" class='activityActions'> <xsl:call-template name="createIssueActionButtons"/> </div> </td></tr></table> <xsl:if test="not($issueNode)"> <script language="javascript"> sprt_remember_user_entered_values(); </script> </xsl:if> <xsl:if test="$audience='ux'"> <script language="javascript"> for (collapsed in defaultCollapsed) { var divId = 'classLabel' + defaultCollapsed[collapsed]; toggleVisibility(document.getElementById(divId)); } </script> </xsl:if> </div> </xsl:template> <xsl:template match="xs:element" name="element"> <xsl:param name="value"/> <xsl:param name="node" select="/.." /> <xsl:param name="id" select="@name" /> <xsl:param name="siclass"/> <xsl:param name="strHTMLID"/> <xsl:param name="strHTMLIDParent"/> <xsl:param name="toggleable" select="true()"/> <xsl:param name="typeName" select="@type"/> <xsl:param name="type" select="$schemaFull/xs:schema/xs:*[not(self::xs:element | self::xs:annotation)][@name=$typeName]" /> <!-- $schemaFull/xs:schema/*[@name=$typeName] picks more than one if there are duplicate type definitions This needs to be fixed to pick up just the first match. For now assume duplicate type def's will not exist. alert('<xsl:value-of select="count($type)"/>'); to Debug. --> <xsl:variable name="style" > <xsl:choose> <xsl:when test="xs:annotation/xs:appinfo/rqa:style"> <xsl:value-of select="xs:annotation/xs:appinfo/rqa:style"/> </xsl:when> <xsl:when test="$type/xs:annotation/xs:appinfo/rqa:style"> <xsl:value-of select="$type/xs:annotation/xs:appinfo/rqa:style"/> </xsl:when> <xsl:otherwise> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="valui" > <xsl:choose> <xsl:when test="xs:annotation/xs:appinfo/rqa:valui"> <xsl:value-of select="xs:annotation/xs:appinfo/rqa:valui"/> </xsl:when> <xsl:when test="$type/xs:annotation/xs:appinfo/rqa:valui"> <xsl:value-of select="$type/xs:annotation/xs:appinfo/rqa:valui"/> </xsl:when> <xsl:otherwise> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="label" > <xsl:call-template name="getLabel"> <xsl:with-param name="node" select="$node"/> <xsl:with-param name="type" select="$type"/> </xsl:call-template> </xsl:variable> <xsl:variable name="attribute"> <xsl:call-template name="getAttribute"> <xsl:with-param name="node" select="$node"/> <xsl:with-param name="type" select="$type"/> </xsl:call-template> </xsl:variable> <xsl:variable name="elementId"> <xsl:choose> <xsl:when test="not($typeName)"> <xsl:choose> <xsl:when test="starts-with(name($node), $guidPrefix)"> <xsl:value-of select="substring-after(name($node), $guidPrefix)" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="name($node)" /> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="starts-with(@name, $guidPrefix)"> <xsl:value-of select="substring-after(@name, $guidPrefix)" /> </xsl:when> <xsl:when test="starts-with($typeName, $guidPrefix)"> <xsl:value-of select="substring-after($typeName, $guidPrefix)" /> </xsl:when> <xsl:when test="starts-with(name(.), $guidPrefix)"> <xsl:value-of select="substring-after(name(.), $guidPrefix)" /> </xsl:when> <xsl:when test="@name"> <xsl:value-of select="@name" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="name(.)" /> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:variable> <!-- alert('<xsl:value-of select="$elementId"/>'); --> <xsl:choose> <xsl:when test="$type[self::xs:complexType]"> <!-- When $type is a Complex Type --> <xsl:variable name="classcontent"> <xsl:apply-templates select="$type"> <xsl:with-param name="id" select="$elementId" /> <xsl:with-param name="node" select="$node" /> <xsl:with-param name="style" select="$style" /> <xsl:with-param name="strHTMLID" select="$strHTMLID" /> <xsl:with-param name="strHTMLIDParent" select="$strHTMLIDParent" /> <xsl:with-param name="label" select="$label"/> <xsl:with-param name="attribute" select="$attribute"/> <xsl:with-param name="toggleable" select="$toggleable"/> </xsl:apply-templates> </xsl:variable> <xsl:copy-of select="$classcontent"/> </xsl:when> <xsl:otherwise> <xsl:variable name="pfnValidate" select="generate-id()"/> <xsl:variable name="oldValId" > <xsl:value-of select="concat(substring-before($id, '::'), '::')"/> <xsl:choose> <xsl:when test="$node/../rqa:instancename"> <xsl:value-of select="$node/../rqa:instancename"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="'[INSTANCENAME]'"/> </xsl:otherwise> </xsl:choose> <xsl:value-of select="concat('::',$elementId)"/> </xsl:variable> <xsl:variable name="propertyLabel"> <xsl:if test="not(@name) or @name!='sik_iss_typeparents'"> <xsl:call-template name="propertyLabel"> <xsl:with-param name="label" select="$label"/> <xsl:with-param name="propId" select="$oldValId"/> <xsl:with-param name="attribute" select="$attribute" /> <xsl:with-param name="showLabel" select="(($audience = 'ux' and not(key('kernelPropHiddenListUX',$node))) or ($audience = 'an' and not(key('kernelPropHiddenListAN',$node)))) and name($node) != 'email_notify' and name($node) != 'email_addr' and name($node) != 'other_email_notify' and name($node) != 'other_email_addr'" /> </xsl:call-template> </xsl:if> </xsl:variable> <xsl:variable name="parentIssueTypeHTML"> <xsl:if test="@name and @name='sik_iss_typeparents'"> <a href="javascript:onSelectIssueTypeParent(\'{@default}\');"><xsl:value-of select="$label"/></a> </xsl:if> </xsl:variable> <xsl:variable name="propertyElement"> <xsl:choose> <xsl:when test="@name and @name='sik_iss_typeparents'"> </xsl:when> <xsl:when test="not($typeName)"> <!-- issue details - some xml --> <xsl:apply-templates select="$node"> <xsl:with-param name="valui" select="$valui" /> <xsl:with-param name="value" select="$node/rqa:value" /> <xsl:with-param name="id" select="$oldValId" /> <xsl:with-param name="siclass" select="$siclass" /> <xsl:with-param name="pfnValidate" select="$pfnValidate" /> <xsl:with-param name="attribute" select="$attribute"/> </xsl:apply-templates> </xsl:when> <xsl:when test="not($type)"> <!-- just a simple node: eg: xs:string --> <xsl:apply-templates select="$typeName"> <xsl:with-param name="valui" select="$valui" /> <xsl:with-param name="value"> <xsl:choose> <xsl:when test="$node/rqa:value"><xsl:copy-of select="$node/rqa:value"/></xsl:when> <xsl:otherwise><xsl:value-of select="@default"/></xsl:otherwise> </xsl:choose> </xsl:with-param> <xsl:with-param name="id" select="$oldValId" /> <xsl:with-param name="siclass" select="$siclass" /> <xsl:with-param name="pfnValidate" select="$pfnValidate" /> <xsl:with-param name="attribute" select="$attribute"/> </xsl:apply-templates> </xsl:when> <xsl:otherwise> <!-- $type is a defined simple type --> <xsl:apply-templates select="$type"> <xsl:with-param name="value" > <xsl:choose> <xsl:when test="$node/rqa:value"><xsl:copy-of select="$node/rqa:value"/></xsl:when> <xsl:otherwise><xsl:value-of select="@default"/></xsl:otherwise> </xsl:choose> </xsl:with-param> <xsl:with-param name="id" select="$oldValId" /> <xsl:with-param name="siclass" select="$siclass" /> <xsl:with-param name="valui" select="$valui" /> <xsl:with-param name="pfnValidate" select="$pfnValidate" /> <xsl:with-param name="attribute" select="$attribute"/> </xsl:apply-templates> </xsl:otherwise> </xsl:choose> </xsl:variable> if('<xsl:value-of select="$node/rqa:value"/>' != '') oldProps<xsl:value-of select="$strHTMLIDParent"/>['<xsl:value-of select="$oldValId"/>'] = '<xsl:value-of select="$node/rqa:value"/>'; else oldProps<xsl:value-of select="$strHTMLIDParent"/>['<xsl:value-of select="$oldValId"/>'] = ''; var parentClassInstance = false; var propertyHTML = '<td ><div>'; <xsl:if test="@name and @name='sik_iss_type'"> propertyHTML += parentITHTML + '<br/>'; parentITHTML = ""; </xsl:if> <xsl:if test="@name and @name='sik_iss_typeparents'"> parentITHTML += '<xsl:copy-of select="$parentIssueTypeHTML"/> > '; </xsl:if> propertyHTML += '<xsl:copy-of select="$propertyElement"/></div></td>'; var propSIClass = '<xsl:value-of select="$type//si:harvest/@class"/>'; var propSIProp = '<xsl:value-of select="$type//si:harvest/@property"/>'; if(propSIProp == "") propSIProp = '<xsl:value-of select="$typeName"/>'; var classSIClass = '<xsl:value-of select="$siclass"/>'; var propInstances = '<xsl:value-of select="$type//si:harvest/si:instances"/>'; if(propInstances == ".") parentClassInstance = true; if( propSIClass != "" && !parentClassInstance){ if(propSIClass != classSIClass) { // Property SI maps override ! Although the class may map other props to some other SI class these are Harvested independently. var property = propertyHTML; propertyHTML = ""; var selRe = /select.*?>(.+)<\/select/; var results = selRe.exec(property); if(propInstances == "") propInstances = "*"; if(propInstances == "*" || propInstances == "?") { if(!g_bSmartIssueCreated) { createIssue("RequestAssist Harvest Issue"); g_bSmartIssueCreated=true; } propInstances = getClassInstances(propSIClass); } propInstances = propInstances.split(","); if(!results) { var val = ""; if(propInstances.length > 1) { for(propInstance in propInstances) { val += propInstance + "," + getSmartVal(propSIClass + "::?::" + propSIProp) + "|"; } } else val = getSmartVal(propSIClass + "::?::" + propSIProp); selRe = /(value=".*?").*/; var results = selRe.exec(property); if(!results) { selRe = /textarea.*?(>.+<)\/textarea/; var results = selRe.exec(property); if(!results) { // Unknown don't know how to set value. propertyHTML = property + val; } else { if(!g_bSmartIssueCreated) { createIssue("RequestAssist Harvest Issue"); g_bSmartIssueCreated=true; } propertyHTML = property.replace(results[1], '>' + val + '<'); } } else { if(!g_bSmartIssueCreated) { createIssue("RequestAssist Harvest Issue"); g_bSmartIssueCreated=true; } propertyHTML = property.replace(results[1], 'value="' + val + '"'); } } else { var optHTML = ""; var re = /<option(.*?)>(.+)\/option>/; for(propInstance in propInstances) { var optResults = re.exec(results[1]); if(!g_bSmartIssueCreated) { createIssue("RequestAssist Harvest Issue"); g_bSmartIssueCreated=true; } var val = getSmartVal(propSIClass + "::" + propInstances[propInstance] + "::<xsl:value-of select="$type//si:harvest/@property"/>"); optHTML += "<option" + optResults[1] + ">" + val + "</option>"; } propertyHTML = property.replace(re, optHTML); } } } <xsl:choose> <xsl:when test="$siclass"> if( propSIClass == "" || propSIClass == classSIClass) { if(!g_harvestInfo.classes['<xsl:value-of select="substring-before($id, '::')"/>']) g_harvestInfo.classes['<xsl:value-of select="substring-before($id, '::')"/>'] = new Array(); var rqaClassProps = g_harvestInfo.classes['<xsl:value-of select="substring-before($id, '::')"/>']; //alert('<xsl:value-of select="substring-before($id, '::')"/>' + '::?::' + '<xsl:value-of select="$id"/> = ' + classSIClass + '::[INSTANCENAME]::' + propSIProp); if(parentClassInstance && propSIClass != "") rqaClassProps['<xsl:value-of select="$elementId"/>'] = propSIClass + '::[INSTANCENAME]::' + propSIProp; else rqaClassProps['<xsl:value-of select="$elementId"/>'] = classSIClass + '::[INSTANCENAME]::' + propSIProp; } </xsl:when> <xsl:otherwise> </xsl:otherwise> </xsl:choose> classHTMLBody<xsl:value-of select="$strHTMLIDParent"/> += '<tr><xsl:copy-of select="$propertyLabel"/>' + propertyHTML + '</tr>'; <xsl:if test="normalize-space($attribute) = 'required'"> reqProps<xsl:value-of select="$strHTMLIDParent"/>['<xsl:value-of select="$oldValId"/>'] = ''; </xsl:if> function validateme<xsl:value-of select="$pfnValidate"/>() { clearErrorMessage(); <xsl:call-template name="validationScript"> <xsl:with-param name="type" select="$type"/> <xsl:with-param name="typeName" select="$typeName"/> </xsl:call-template> return clearInvalidity(event.srcElement); } </xsl:otherwise> </xsl:choose> </xsl:template>
Current Thread |
---|
|
<- Previous | Index | Next -> |
---|---|---|
RE: [xsl] Maintaining XSL ..., cknell | Thread | [xsl] appending to result-document, Rahil |
Re: [xsl] How to get to the XML Dec, Kenneth Stephen | Date | [xsl] User defined SAX ContentHandl, Ramkumar Menon |
Month |