Search Tools Links Login

ASP and XML Surveys


Ever wanted a survey on your site? But don't have a database? Well, by using ASP and XML you can! Features single voting, survey expiry, past survey results, and many nore...

Original Author: George Leithead

Code

You've seen them all over the web. They've popped up more and more. What am I talking about? I'll tell you wat I'm talking about, surveys and user poll's, thats what. Well, I have some code here that will allow you to implement a survey all without a database and other expensive components.



All code mentioned in this article can be downloaded from here, can can be discussed here



What do we need from a survey? Well, simply we need a question, answers to the question, and the ability to record the number of votes. This is acheived with the following simply XML structure:


<survey voters="1">

    <id />

    <question />

    <answer votes="1" />

    <dateend />

</survey>




Breaking this down, we can see that we have a survey node. We can have as many survey nodes as we like. This survey node has one attribute, voters. This will be used to record the number of votes taken for this survey. Each survey, has an ID, question and answer element(s). The id is used to uniquley identify each survey. Each survey has a question, and each survey can have one or more answers. After all a question with only one answer would be prity pointless. The last element is date end. This is used to specify when the survey is to end.



You'll also notice that the answer element has a votes attribute. This will be used to record the number of votes for the selected answer.



An exam of a populated survey might be:


<survey voters="1">

<id />1</id>

<question>Do you think surveys are a good idea?</question>

<answer votes="0">Great</answer>

<answer votes="1">Not Bad</answer>

<answer votes="0">Average</answer>

<answer votes="0">Poor</answer>

<answer votes="0">Rubbish!</answer>

<dateend>20011231</dateend>

</survey>




Now that we have defined the information we need, next we need to define a way to display it. By using XSL this is made relativley simple:


<render id="vradio">

    <FORM ACTION="Poll.asp" TARGET="Poll" METHOD="POST" onSubmit="window.open('','Poll','width=300,height=120,toolbar=no,location=no,directories=no,status=no,menubar=no,resizable=no,scrollbars=no');">

    <INPUT TYPE="HIDDEN" NAME="ID">

        <xsl:attribute name="VALUE"><xsl:value-of select="id"/></xsl:attribute>

    </INPUT>

    <TABLE BORDER="1" CELLPADDING="0" CELLSPACING="0" WIDTH="280" SUMMARY="Survey">

    <TR>

        <TH>Survey</TH>

    </TR>

    <TR>

        <TD ALIGN="center">

            <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%" HEIGHT="100%" SUMMARY="Survey Question and Answers">

            <TR>

                <TH COLSPAN="2"><xsl:value-of select="question"/></TH>

            </TR>

            <xsl:for-each select="answer">

            <TR>

                <TD ><xsl:value-of /></TD>

                <TD ><INPUT TYPE="radio" NAME="Poll">

                        <xsl:attribute name="value"><xsl:value-of/></xsl:attribute>

                    </INPUT>

                </TD>

            </TR>

            </xsl:for-each>

            <TR>

                <TD ALIGN="right" COLSPAN="2"><INPUT TYPE="submit" NAME="Submit" VALUE="Vote" /></TD>

            </TR>

            </TABLE>

        </TD>

    </TR>

    </TABLE>

    </FORM>

</render>



<render id="results">

    <TABLE BORDER="1" CELLPADDING="0" CELLSPACING="0" WIDTH="280" SUMMARY="Survey Results">

    <TR>

        <TH>Survey Result</TH>

    </TR>

    <TR>

        <TD ALIGN="center">

            <TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%" HEIGHT="100%" SUMMARY="Survey Result">

            <TR>

                <TH COLSPAN="3"><xsl:value-of select="question"/></TH>

            </TR>

            <TR>

                <TD COLSPAN="3" ALIGN="CENTER">Total Voters: <xsl:value-of select="@voters"/></TD>

            </TR>

            <xsl:for-each select="answer">

            <TR>

                <TD ALIGN="RIGHT">

                    <IMG SRC="Images/Vote.gif" HEIGHT="10" ALT="Votes">

                    <xsl:attribute name="WIDTH"><xsl:eval>Math.round(this.getAttribute("votes")/this.parentNode.getAttribute("voters") * 100)</xsl:eval></xsl:attribute>

                    </IMG>

                </TD>

                <TD ALIGN="RIGHT">

                    <xsl:eval>Math.round(this.getAttribute("votes")/this.parentNode.getAttribute("voters") * 100)</xsl:eval>%

                </TD>

                <TD WIDTH="100%"><xsl:value-of/></TD>

            </TR>

            </xsl:for-each>

            </TABLE>

        </TD>

    </TR>

    <TR>

        <TD ALIGN="center"><A HREF="ViewPastPolls.asp">View Results of past surveys</A><IMG SRC="http://forums/internetwideworld.com/Images/Blank.gif" height="0" width="0" alt="Weaval" /></TD>

    </TR>

    </TABLE>

</render>


Now we have our information, and a template to display it in, we now need to select the correct survey for display. Firstly, we need to load the XML and XSL files:



Application("SurveyPath")  = server.MapPath("src/") & "" ' NEED to add on the extra
Application("SurveySource") = server.MapPath("src/surveys.xml")
Application("SurveyStyle") = server.MapPath("src/surveys.xsl")
Function loadSurveys()
Dim source, style, rootPath
rootPath = Application("SurveyPath")
set source = Server.CreateObject("Microsoft.FreeThreadedXMLDOM")
source.async = false
source.load Application("SurveySource")
set style = Server.CreateObject("Microsoft.FreeThreadedXMLDOM")
style.async = false
style.load Application("SurveyStyle")
application.lock
set application("survey") = source
set application("style") = style
application.unlock
end Function


Next we need to actually display the survey. This is acheived by selecting the first survey where the dateend is greater than today, we can select the correct survey.



Function GetDate()
'Produces YYYYMMDD
DIM dYear : dYear = Year(Now())
DIM dMonth : dMonth = Month(Now())
DIM dDay  : dDay = Day(Now())
DIM iID  : iID = 1
DIM iLoop : iLoop = 1
If Len(dMonth) < 2 then dMonth = "0" & dMonth
If Len(dDay) < 2 then dDay = "0" & dDay

GetDate = dYear & dMonth & dDay
End Function
Function DisplayLatestSurvey()
DIM oRequiredNode
DIM oSource
DIM oStyle
DIM oOutNode
DIM sRender : sRender = "vradio"
DIM iID  : iID = 1
DIM dDate : dDate = GetDate()
set oSource = Application("survey")
set oStyle = Application("style")
set oRequiredNode = oSource.selectSingleNode("surveylist/survey[dateend[. > """ & dDate & """]]")
if NOT oRequiredNode is nothing then
iID = oRequiredNode.selectSingleNode("id").text ' Get the Survey ID!
If InStr(Request.Cookies("Survey"),":" & iID & ":") > 0 then
sRender = "results"
End If
set oOutNode = oStyle.selectSingleNode("xsl:stylesheet/render[@id=""" & sRender & """]")
if NOT oOutNode is nothing then
' Apply the style to the source!
DisplayLatestSurvey = oRequiredNode.transformNode(oOutNode)
else
DisplayLatestSurvey = "ERROR: Either the XSL file is incorrect or the render identifier is not found"
end if
else
DisplayLatestSurvey = "ERROR: Either no survey exists for this period or the survey was not found"
end if
' Tidy Up!!!
set oOutNode = nothing
set oRequiredNode = nothing
set oStyle = nothing
set oSource = nothing
End Function


Within the DisplayLatestSurvey function there are two items to pay particular attention to. Firstly, sRender = "vradio" specifies the render style we want, which is contained within the XSL file.

The second item of note, is the Request.Cookies. Obviously, if some one has already voted in the survey, we don't want them to vote again. So, we determine if the user has a cookie this survey. If they do not, simply display the vradio XSL display. Oterhwise, they have already voted, and we change the XSL render to be results. This XSL render displays the actual voting for the survey.

So far, we've only displayed the survey and the survey results. But what about letting the user register their vote? This is by adding 1 to not only the number of voters, but also by adding 1 to the number of votes for an answer.



function voteSurvey(ByVal sID, ByVal sVote, ByRef bResult)
Dim findNode, result, rootPath, source
if sVote<>"" then
  set source = application("survey")
  set findNode = source.selectSingleNode("surveylist/survey[id[. = """ & sID & """]]/answer[.=""" & sVote & """]")
  if not findNode is nothing then
  findNode.setAttribute "votes", findNode.getAttribute("votes") + 1
  set findNode = findNode.parentNode
  findNode.setAttribute "voters", findNode.getAttribute("voters") + 1
rootPath = Application("SurveyPath")
  saveSurveys source
  bResult = true
  result = "Your vote has been accepted!"
  else
result="Your vote choice for this poll is invalid!"
  end if
end if
voteSurvey = result
if bResult then CALL SetSurveyCookie(sID)
end function
function saveSurveys(obj)
Dim rootPath,s
rootPath = Application("SurveyPath")
obj.save rootPath & "surveys.xml"
for each s in application.contents
if left(s,6)="SURVEY" and s<>"SURVEY" then
application.lock
set application(s) = nothing
application.unlock
end if
next
end function
Function SetSurveyCookie(ByVal iID)
Response.Cookies("Survey") = ":" & iID & ":"
Response.Cookies("Survey").Expires = "January 1, 2011"
End Function


Once we register the vote, we need to then save the results, and 'unload' the previous version of the XML file, so that the new results can be viewed.

Then in order to prevent the user from re-submitting another vote, we send the user a cookie with the survey id that they voted in.



As additional functionality, we may also want to display a list of 'past' surveys and their results. This is acheived by implementing a new XSL render template, and some more ASP code. These and more can be found in the downloadable code, from here.



To discuss this article and the code go here.Weaval

About this post

Posted: 2002-06-01
By: ArchiveBot
Viewed: 74 times

Categories

ASP/ HTML

Attachments

No attachments for this post


Loading Comments ...

Comments

No comments have been added for this post.

You must be logged in to make a comment.