GessWurker
asked on
ASP or PERL for html form data --> xml transform --> xml query insert and response ??
I've got an ASP page (provided by a vendor) that accepts html form data, transforms it into valid xml, submits the xml as an xml query (an INSERT in this case), receives the XML search engine's response, transforms the XML to HTML, and displays the response to the user. (See the code that does this at the bottom of this message.) ASP seems to be doing all of this efficiently by making use of MSXML 4 Core services and a few javascript functions.
My question: Does the scenario outlined above seem like something that could be done efficiently via PERL? I'm using PERL quite a bit to transform xml database content to html, but I haven't used PERL at all to go the other direction. I'd prefer to use more PERL rather than add an ASP piece, since I don't use ASP anywhere else on my sites. Maybe I'm not thinking straight, but I'd like to stick to PERL if possible. However, since I'm not sure whether this makes sense, I'm asking PERL experts what they would advise. So...
What would you advise? If it seems like PERL could do a good job with this, I'll post questions on how to do that. But first, I just need to know whether PERL would be a good choice, at least as good as the ASP page. Maybe PERL could be even better? Thanks for your responses in advance.
Here's the ASP page I mentioned above. It's for adding records to an "Inmagic" database:
<%@ Language=JavaScript %>
<HTML>
<HEAD>
<%
// JavaScript code for WP Pro Tutorial
// Copyright © 2002, Inmagic, Inc., Woburn, MA, USA. All rights reserved.
//======================== ========== ========== ======
//GLOBAL Variables
//======================== ========== ========== ======
var queryError = null; //queryError holds an error generated for display
//variables for writing response messages
var strAc, strSucceeded, strFailed, strStatus, strRecResult, entrySeparator;
var strRecInfo = '';
// for display of Debug
var strXmlOutput,sServerName;
/* 1. Build the XML Query with the buildWpQuery function */
var strXmlInput = buildWpQuery();
/* 2. Send the XML Query to WP Pro and get the XML Response
from WP Pro to the XML Query */
var strReturnedXml = submitWpXml(strXmlInput);
/* 3. Process The XML returned by WP Pro. This will place the
the information extracted from the WP Pro response in variables */
processWpXml(strReturnedXm l);
//======================== ========== ========== ========
// Function: buildWpQuery
// Purpose: build XML Query
// Parameters: none
// Returns: XML Query string for WP Pro insert
// Note:
//======================== ========== ========== ========
function buildWpQuery()
{
//build the WP Pro XML query as one long string
strXmlInput = '<?xml version="1.0" ?>\n' +
'<Query xmlns="http://www.inmagic.com/webpublisher/query">\n' +
'<AC>insert</AC>\n' +
'<TN>Cars</TN>\n' + //CARS IN FINAL
'<KeyFields>\n' +
' <KeyField>Product Number</KeyField>\n' +
' <KeyField>Name</KeyField>\ n' +
'</KeyFields>\n' +
'<Recordset>\n' +
' <Record>\n' +
//Get the Record Data from the form
//The first two fields do not allow multiple entries so Request.QueryString
// is used directly
' <Name><![CDATA[' + Request.QueryString("Name" ) + ']]></Name>\n' +
' <Product-Number><![CDATA[' + Request.QueryString("Produ ct-Number" ) + ']]></Product-Number>\n' +
makeMultiple("Features",", ") +
makeMultiple("Date-Release d",", ") +
makeMultiple("Type",", ") +
makeMultiple("Skill-Level" ,", ") +
makeMultiple("Description" ,", ");
//close the recordset
strXmlInput += ' </Record>\n</Recordset>\n< /Query>';
return strXmlInput;
}
//======================== ========== ========== ========
// Function: makeMultiple()
// Purpose: Make multiple entries
// Parameters: field - Field name and the form element name
// delimiter - The character that denotes new
// multiple entry
// Returns: XML Query field elements
// Note:
//======================== ========== ========== ========
function makeMultiple(field, delimiter)
{
var xmlString = '';
var strField = new String(Request.QueryString (field));
var arrField = strField.split(delimiter);
for(i=0;i<arrField.length; i++)
{
xmlString += ' <' + field + '><![CDATA[' + arrField[i] + ']]></' + field + '>\n';
}
return xmlString;
}
//======================== ========== ========== ========
// Function: submitWpXml
// Purpose: submit XML string to WP Pro
// Parameters: xmlString - a string of xml
// Returns: HTTP response as text
// Note: url variable is defined outside function
//======================== ========== ========== ========
function submitWpXml(xmlString)
{
// create an instancee of the MSXML 4 ServerHTTPRequest object to send XML to WPPro
var xmlhttp = new ActiveXObject("MSXML2.Serv erXMLHTTP. 4.0");
sServerName = Request.ServerVariables("S ERVER_NAME ");
if (sServerName == "")
sServerName = "localhost";
// Initializes an MSXML2.ServerXMLHTTP request and specifies the method, URL, and authentication information for the request.
xmlhttp.open( "POST", "http://"+sServerName+"/dbtw-wpd/ exec/dbtwp ub.dll", false, "", "" ); //UPDATE FOR RELEASE
//set header
xmlhttp.setRequestHeader( "Content-Type", "text/xml" );
xmlhttp.send (xmlString); // send the xml to WP Pro and wait for a response
// get the response from WP as a string of text,
return xmlhttp.responseText;
//return xmlhttp.responseXML would get the repsponse as an xml object
}
//======================== ========== ========== ========
// Function: processWpXml
// Purpose: extract information from WP response
// Parameters: strXml - WP Pro XML response as string
// Returns: nothing
// Note: populates global Variables: queryError,
// strAc, intSucceeded, intFailed, strStatus,
// strRecResult, strRecInfo
//======================== ========== ========== ========
function processWpXml(strXml)
{
try
{
var objWpResponse = new ActiveXObject("Msxml2.DOMD ocument.4. 0");
/* this lines are probably not needed but I am keeping them here now in case */
//objWpResponse.setPropert y("Selecti onLanguage ", "XPath");
objWpResponse.setProperty( 'Selection Namespaces ', 'xmlns:inm="http://www.inmagic.com/webpublisher/records-processed"');
objWpResponse.async = false;
if (objWpResponse.loadXML(str Xml))
{
strXmlOutput = objWpResponse.xml; //put XML response in textarea for debug
//check for wp error
var ErrorNode = objWpResponse.selectSingle Node('/inm :Results/i nm:Error') ;
if (ErrorNode == null)
{
//read attributes from the Records-Processed in global vars
var objRecProcNode = objWpResponse.selectSingle Node('/inm :Results/i nm:Records -Processed ');
strAc = objRecProcNode.getAttribut e("AC");
intSucceeded = objRecProcNode.getAttribut e("succeed ed");
intFailed = objRecProcNode.getAttribut e("failed" );
//set the value of Global Var that displays action status
if(intSucceeded > 0)
strStatus = "succeeded";
if(intFailed > 0)
strStatus = "failed";
//Get Result attribute of the first record processed.
var objIndvRecProcNode = objRecProcNode.firstChild;
strRecResult = objIndvRecProcNode.getAttr ibute("Res ult");
//loop through the child elements of the first Rec processed.
//This will be the keyFields and error
if(objIndvRecProcNode.hasC hildNodes)
{
var recNodeList = objWpResponse.selectNodes( '/inm:Resu lts/inm:Re cords-Proc essed/inm: Record-Pro cessed/*') ;
for(i=0;i<recNodeList.leng th;i++)
{
var objNode = recNodeList.nextNode();
strRecInfo += '<b>' + stripPrefix(objNode.nodeNa me) + ':</b> '
strRecInfo += objNode.text + '<br/>';
}
}
}
else
{
queryError = ErrorNode.text;
}
}
else
{
queryError = "Error: " + objWpResponse.parseError.r eason;
}
}
catch(objErr)
{
queryError = "Error: " + objErr.message;
}
}
//======================== ========== ========== ========
// Function: stripPrefix
// Purpose: strip the "inm:" of the field name for display
// Parameters: the string containing the element name
// Returns: elemenet name without inm:
// Note:
//======================== ========== ========== ========
function stripPrefix(elementName)
{
var intColLoc = elementName.indexOf(":") + 1;
var strName = elementName.substring(intC olLoc, elementName.length)
return strName;
}
%>
<META name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
<STYLE> body {font-family:arial;}
h5 {color:red}
b {color:blue}
</STYLE>
</HEAD>
<BODY>
<H5><% =queryError %></H5>
<P><STRONG>Your record
<%=strAc%>
has
<%=strStatus%>
</STRONG>
</P>
<P><STRONG>Record
<%=strRecResult%>
:<BR>
</STRONG>
<%=strRecInfo%>
</P>
<P><STRONG>XML SENT:<BR>
</STRONG><TEXTAREA rows="17" cols="92" id="Textarea1" name="Textarea1"><% =strXmlInput %></TEXTAREA>
</P>
<P><STRONG>XML Returned:<BR>
</STRONG><TEXTAREA rows="17" cols="92" id="Textarea3" name="Textarea3"><% =strXmlOutput%></TEXTAREA>
</P>
</BODY>
</HTML>
My question: Does the scenario outlined above seem like something that could be done efficiently via PERL? I'm using PERL quite a bit to transform xml database content to html, but I haven't used PERL at all to go the other direction. I'd prefer to use more PERL rather than add an ASP piece, since I don't use ASP anywhere else on my sites. Maybe I'm not thinking straight, but I'd like to stick to PERL if possible. However, since I'm not sure whether this makes sense, I'm asking PERL experts what they would advise. So...
What would you advise? If it seems like PERL could do a good job with this, I'll post questions on how to do that. But first, I just need to know whether PERL would be a good choice, at least as good as the ASP page. Maybe PERL could be even better? Thanks for your responses in advance.
Here's the ASP page I mentioned above. It's for adding records to an "Inmagic" database:
<%@ Language=JavaScript %>
<HTML>
<HEAD>
<%
// JavaScript code for WP Pro Tutorial
// Copyright © 2002, Inmagic, Inc., Woburn, MA, USA. All rights reserved.
//========================
//GLOBAL Variables
//========================
var queryError = null; //queryError holds an error generated for display
//variables for writing response messages
var strAc, strSucceeded, strFailed, strStatus, strRecResult, entrySeparator;
var strRecInfo = '';
// for display of Debug
var strXmlOutput,sServerName;
/* 1. Build the XML Query with the buildWpQuery function */
var strXmlInput = buildWpQuery();
/* 2. Send the XML Query to WP Pro and get the XML Response
from WP Pro to the XML Query */
var strReturnedXml = submitWpXml(strXmlInput);
/* 3. Process The XML returned by WP Pro. This will place the
the information extracted from the WP Pro response in variables */
processWpXml(strReturnedXm
//========================
// Function: buildWpQuery
// Purpose: build XML Query
// Parameters: none
// Returns: XML Query string for WP Pro insert
// Note:
//========================
function buildWpQuery()
{
//build the WP Pro XML query as one long string
strXmlInput = '<?xml version="1.0" ?>\n' +
'<Query xmlns="http://www.inmagic.com/webpublisher/query">\n' +
'<AC>insert</AC>\n' +
'<TN>Cars</TN>\n' + //CARS IN FINAL
'<KeyFields>\n' +
' <KeyField>Product Number</KeyField>\n' +
' <KeyField>Name</KeyField>\
'</KeyFields>\n' +
'<Recordset>\n' +
' <Record>\n' +
//Get the Record Data from the form
//The first two fields do not allow multiple entries so Request.QueryString
// is used directly
' <Name><![CDATA[' + Request.QueryString("Name"
' <Product-Number><![CDATA['
makeMultiple("Features",",
makeMultiple("Date-Release
makeMultiple("Type",", ") +
makeMultiple("Skill-Level"
makeMultiple("Description"
//close the recordset
strXmlInput += ' </Record>\n</Recordset>\n<
return strXmlInput;
}
//========================
// Function: makeMultiple()
// Purpose: Make multiple entries
// Parameters: field - Field name and the form element name
// delimiter - The character that denotes new
// multiple entry
// Returns: XML Query field elements
// Note:
//========================
function makeMultiple(field, delimiter)
{
var xmlString = '';
var strField = new String(Request.QueryString
var arrField = strField.split(delimiter);
for(i=0;i<arrField.length;
{
xmlString += ' <' + field + '><![CDATA[' + arrField[i] + ']]></' + field + '>\n';
}
return xmlString;
}
//========================
// Function: submitWpXml
// Purpose: submit XML string to WP Pro
// Parameters: xmlString - a string of xml
// Returns: HTTP response as text
// Note: url variable is defined outside function
//========================
function submitWpXml(xmlString)
{
// create an instancee of the MSXML 4 ServerHTTPRequest object to send XML to WPPro
var xmlhttp = new ActiveXObject("MSXML2.Serv
sServerName = Request.ServerVariables("S
if (sServerName == "")
sServerName = "localhost";
// Initializes an MSXML2.ServerXMLHTTP request and specifies the method, URL, and authentication information for the request.
xmlhttp.open( "POST", "http://"+sServerName+"/dbtw-wpd/
//set header
xmlhttp.setRequestHeader( "Content-Type", "text/xml" );
xmlhttp.send (xmlString); // send the xml to WP Pro and wait for a response
// get the response from WP as a string of text,
return xmlhttp.responseText;
//return xmlhttp.responseXML would get the repsponse as an xml object
}
//========================
// Function: processWpXml
// Purpose: extract information from WP response
// Parameters: strXml - WP Pro XML response as string
// Returns: nothing
// Note: populates global Variables: queryError,
// strAc, intSucceeded, intFailed, strStatus,
// strRecResult, strRecInfo
//========================
function processWpXml(strXml)
{
try
{
var objWpResponse = new ActiveXObject("Msxml2.DOMD
/* this lines are probably not needed but I am keeping them here now in case */
//objWpResponse.setPropert
objWpResponse.setProperty(
objWpResponse.async = false;
if (objWpResponse.loadXML(str
{
strXmlOutput = objWpResponse.xml; //put XML response in textarea for debug
//check for wp error
var ErrorNode = objWpResponse.selectSingle
if (ErrorNode == null)
{
//read attributes from the Records-Processed in global vars
var objRecProcNode = objWpResponse.selectSingle
strAc = objRecProcNode.getAttribut
intSucceeded = objRecProcNode.getAttribut
intFailed = objRecProcNode.getAttribut
//set the value of Global Var that displays action status
if(intSucceeded > 0)
strStatus = "succeeded";
if(intFailed > 0)
strStatus = "failed";
//Get Result attribute of the first record processed.
var objIndvRecProcNode = objRecProcNode.firstChild;
strRecResult = objIndvRecProcNode.getAttr
//loop through the child elements of the first Rec processed.
//This will be the keyFields and error
if(objIndvRecProcNode.hasC
{
var recNodeList = objWpResponse.selectNodes(
for(i=0;i<recNodeList.leng
{
var objNode = recNodeList.nextNode();
strRecInfo += '<b>' + stripPrefix(objNode.nodeNa
strRecInfo += objNode.text + '<br/>';
}
}
}
else
{
queryError = ErrorNode.text;
}
}
else
{
queryError = "Error: " + objWpResponse.parseError.r
}
}
catch(objErr)
{
queryError = "Error: " + objErr.message;
}
}
//========================
// Function: stripPrefix
// Purpose: strip the "inm:" of the field name for display
// Parameters: the string containing the element name
// Returns: elemenet name without inm:
// Note:
//========================
function stripPrefix(elementName)
{
var intColLoc = elementName.indexOf(":") + 1;
var strName = elementName.substring(intC
return strName;
}
%>
<META name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
<STYLE> body {font-family:arial;}
h5 {color:red}
b {color:blue}
</STYLE>
</HEAD>
<BODY>
<H5><% =queryError %></H5>
<P><STRONG>Your record
<%=strAc%>
has
<%=strStatus%>
</STRONG>
</P>
<P><STRONG>Record
<%=strRecResult%>
:<BR>
</STRONG>
<%=strRecInfo%>
</P>
<P><STRONG>XML SENT:<BR>
</STRONG><TEXTAREA rows="17" cols="92" id="Textarea1" name="Textarea1"><% =strXmlInput %></TEXTAREA>
</P>
<P><STRONG>XML Returned:<BR>
</STRONG><TEXTAREA rows="17" cols="92" id="Textarea3" name="Textarea3"><% =strXmlOutput%></TEXTAREA>
</P>
</BODY>
</HTML>
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
kandura:
Thanks for pointing me to HTML::Template. I was using perl cgi includes in an shtml page, but using HTML::Template, my form seems to draw about 10 times faster! Works great!!
Thanks for pointing me to HTML::Template. I was using perl cgi includes in an shtml page, but using HTML::Template, my form seems to draw about 10 times faster! Works great!!
ASKER
oops. Skip that last question. I've got everything I need in the javascript from the sample above. It's just the vb stuff I might need to address.
ASKER
OK. I miss-spoke again. The javascript I've got is asp & msxml core services dependent. At the moment, I'm thinking I'd do best (or fastest, at least) to try for a mixed asp/perl solution.
Tintin: Can you give an example of PERL/ASP? Maybe something like including execultion of helloworld.pl in an asp page?
Tintin: Can you give an example of PERL/ASP? Maybe something like including execultion of helloworld.pl in an asp page?
ASKER
rats! Looks like I'd have to install PERLASPX (from Activestate) in order to combine PERL functionality w/an existing ASP page. Maybe I should just go ahead and buy PerlASPX. Don't know yet. In any case, I'll close this question out now and start asking new questions about how to duplicate the ASP functionality w/pure PERL. Thanks again for your help thus far. Expect new questions soon!
ASKER
Thanks Tintin. I'm running IIS. Am hoping (at this point) to eventually work out a pure PERL solution. But I may end up using the ASP I've got for all the xml formatting and submitting and running some PERL actions onload when the ASP page opens.
If you care to chime in on my latest question, please take a look at: https://www.experts-exchange.com/questions/21021354/Transform-html-form-data-into-well-formed-xml.html
If you care to chime in on my latest question, please take a look at: https://www.experts-exchange.com/questions/21021354/Transform-html-form-data-into-well-formed-xml.html
Actually, ActiveState perl comes with everything you need for ASP and perl. Their canonical example is this:
<%@ Language=PerlScript %>
<%
for($i=0; $i<=10; $i++) {
#
# Your Perl code here
#
}
%>
As you see, very easy to use. The rest works mostly like javascript or vbscript, except that you get to write in perl :-)
All the basic ASP objects are available too, for example $Response->Write("Hello World");
Documentation can be found here: http://aspn.activestate.com/ASPN/docs/ActivePerl/Windows/ActiveServerPages.html
<%@ Language=PerlScript %>
<%
for($i=0; $i<=10; $i++) {
#
# Your Perl code here
#
}
%>
As you see, very easy to use. The rest works mostly like javascript or vbscript, except that you get to write in perl :-)
All the basic ASP objects are available too, for example $Response->Write("Hello World");
Documentation can be found here: http://aspn.activestate.com/ASPN/docs/ActivePerl/Windows/ActiveServerPages.html
ASKER
kandura: Your recommendation sounds promising to me. But I'll need a good deal of guidance. I would really like to go w/PERL.