• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Reverse CFXML ?

Guest
Feb 29, 2008 Feb 29, 2008

Copy link to clipboard

Copied

I've built a client-driven RIA using CF7 as the intermediary to a SQL Server 2005 database.

Data are passed as URL parameters in the existing architecture. A new requirement has surfaced that will require more data to be passed to and stored in the database; URL encoding is not practical for this.

The volume of the data being passed is mutable, ranging from approximately 80 bytes [stored as one table row] up to 24K [stored as (roughly) 300 rows in two tables]. The obvious output choice is XML.

I can pass the data to CF by storing the data as an XML file on the server, then reading it into a CF application using CFFILE. It would be cleaner if there's another mechanism available that could populate a CFXML variable directly, but my research doesn't reveal an obvious choice. [That research has extended through CF8: "Adobe ColdFusion 8 Application Development" Volume 2 by Ben Forta and Raymond Camden.]

Did I miss something? Does anyone out there have an alternative method?

TOPICS
Advanced techniques

Views

1.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

coffeedrinker56 wrote:
> It would be cleaner if there's another mechanism available that could populate a CFXML
> variable directly

Directly from what source? There are quite a few ways to get XML into
and out of ColdFusion. But I am unclear on where you want to directly
'populate a CFXML variable' from?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

What I'd like to see is an extension of the CFXML tab - or of the CFFILE tag - that would allow a direct import of client-originated XML without having a two-step process.

Right now the closest method I can use is...
(1) Client reads form data and formats it as XML;
(2) Client sends XML (via Ajax) to the server, storing the data as "abc.xml";
(3) Client initiates a CF process that reads "abc.xml" using the CFFILE action="read", then validates that it is XML [IsXmlDoc function], and finally parses the XML data into a local variable [XmlParse function].

The process would be much cleaner as:
<cfxml variable="myXmlVar" caseSensitive="yes" port="80" action="read" />

... or as a modification to the cffile tag:

<cffile action="read" port="80" variable="myXmlText" />
<cfset myXML = XmlParse(myXmlText) />

[I would think that the latter would be the easier option to implement.]


Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

Am I understanding correctly that you would like a user to send XML
formated data as a form post?

If so, is there something wrong with this simple process?

<cfset xmlObj = xmlParse(form.xmlField)>

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

or, if the OP would like a user to upload an xml file to the server
(port='80' made me think so), can cfhttp be used to read an xml doc
into a variable?

Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

Azadi wrote:
> or, if the OP would like a user to upload an xml file to the server
> (port='80' made me think so), can cfhttp be used to read an xml doc
> into a variable?
>
> Azadi Saryev
> Sabai-dee.com
> http://www.sabai-dee.com/

<cfhttp...> can be used to read an XML file into a variable from a URL.
But if the file has been uploaded to the server, then <cffile...> is
the proper tag to read its contents and process into a variable.

I presumed the OP wanted to get XML data to the server directly from a
user without them uploading a file.

I'm just a bit unclear what "1) reads form data and formats is as XML"
and "2) sends XML to server" is meant to describe. Is this the desired
process, the current process or just the only solution yet figured out?


Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

right you are re cffile.
i am confused by the OP's requirements/procedural logic, too...

why like that, coffeedrinker?

Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 03, 2008 Mar 03, 2008

Copy link to clipboard

Copied

"why like that, coffeedrinker?"

Prior to this new requirement coming in, the quantity of data being sent to the server at any one time was very limited - typically 100 bytes or less - so adding the data to the URL and sending it as a 'GET' via the XmlHttpRequest object made sense - and it works very well.

The application currently exchanges data via this method with 41 CF scripts that generate XML and 11 XSL files to format. Two other XML files with corresponding XSL files are imported/formatted using DOMDocument techniques. [These last four files are static, but are formatted differently depending upon the privileges assigned to the users' accounts.]

ONE page-length form within the XHTML script is used to contain all of the data as-and-when-needed imported from the server.

It sounds worse than it is: only 27 form fields need to be maintained across all of the functionality. The DOM is manipulated to add/modify/remove other fields as needed.

One short section of JavaScript is a "black hole" intended to keep the form data from ever being submitted to the server. It's there specifically to keep the form from ever being "submitted" to the server and thereby requiring the page to be reloaded.

Yes, it would be easy to read the data using FORM.variable constructs. But re-coding 5,200 lines of JavaScript to incorporate this new requirement makes less sense than sending the XML data as a file and having CFFILE read it.

Currently to accomplish the new requirement the XML data is sent via XmlHttpRequest.send(); the name of the file - it's dynamically generated to keep the user from overwriting his/her own work - is sent as part of the URL.

To answer another questioner: CFHTTP can be used to read the XML file once it's on the server, but CFFILE reads the data as well. So there's no real advantage to using a server-side ajax function for this purpose.

[Maintainability is an issue. I'm a contractor. Some day (presumably) I'll take a position elsewhere, but I'm the only one here with Ajax experience. Other CF experienced people here understand CFFILE since they've used it for ages, but this is the first RIA at this site - and probably the first RIA within this organization.]

The methods I'm using work, but it would be a lot cleaner if the CF process could read the XML directly.

Herb Spencer

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

coffeedrinker56 wrote:
> The methods I'm using work, but it would be a lot cleaner if the CF process
> could read the XML directly.
>
> Herb Spencer

I still do not completely understand your difficulty? I can use CF to
read XML seven ways from Sunday. Do you or do you not want to work with
a file sent as a multi-part request?

Using AJAX does not change the underlining HTTP request-response nature
of web applications, RIA or not. Whether the request comes from a user
action directly from the browser, or inside the browser using
JavaScript, it is still a request no different from any other request to
the server. This request can be a get or a post at your choice. You
are currently using it to post a multi-part request with a file. If you
don't want to use a file, just post a form instead.

Then on the server side, use the URL scope, the FORM scope or
<cffile...> as relevant to how you sent the data.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

Ian:
Thanks for responding.
Neither reading nor writing XML is a problem at either end of the conversation.
Every one of the 41 CF scripts I mentioned earlier either reads or writes XML. [Most read/manipulate the XML data then send - at least - response codes, messages, etc back to the browser as XML.]

If possible, I'd like to skip the generate-file/read-file/delete-file sequence completely. But in this case the volume of data makes the data stream too clumsy when put into the url?p1=v1&p2=v2 ... format.

I can easily use a single JS variable ("myXML" in this case) to pass XML data like this:
var myURL = 'abc.cfm?xmlcontent=' + myXML;
ajax('GET', myURL, true);

["ajax()" is a multi-browser compatible JS function that I wrote specifically to send/receive XML to the server.]

Then, of course, CF can read the XML data as a URL variable, eg:
<cfif IsDefined("URL.xmlcontent") >
<cfset inXML = XmlParse("URL.xmlcontent") />
</cfif>

Now imagine that the "myXML" variable has 300 child nodes, each of which can have two children containing up to 2K (each) of text plus a dozen siblings of comparatively inconsequential sizes. [The actual average size is approximately 60K, but 700K has happened.]

Storing the XML as a file and then reading it into CF using CFFILE results could result in 1.4 Mb conversation; reading it directly - if possible - cuts that conversation by half.

That's my goal. It would be the exact opposite of a cfhttp tag.

Thanks.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

coffeedrinker56 wrote:
> Ian:
> Thanks for responding.
> Neither reading nor writing XML is a problem at either end of the
> conversation.
> Every one of the 41 CF scripts I mentioned earlier either reads or writes
> XML. [Most read/manipulate the XML data then send - at least - response codes,
> messages, etc back to the browser as XML.]
>
> If possible, I'd like to skip the generate-file/read-file/delete-file
> sequence completely. But in this case the volume of data makes the data stream
> too clumsy when put into the url?p1=v1&p2=v2 ... format.
>
> I can easily use a single JS variable ("myXML" in this case) to pass XML
> data like this:
> var myURL = 'abc.cfm?xmlcontent=' + myXML;
> ajax('GET', myURL, true);
>
> ["ajax()" is a multi-browser compatible JS function that I wrote
> specifically to send/receive XML to the server.]
>
> Then, of course, CF can read the XML data as a URL variable, eg:
> <cfif IsDefined("URL.xmlcontent") >
> <cfset inXML = XmlParse("URL.xmlcontent") />
> </cfif>
>
> Now imagine that the "myXML" variable has 300 child nodes, each of which can
> have two children containing up to 2K (each) of text plus a dozen siblings of
> comparatively inconsequential sizes. [The actual average size is approximately
> 60K, but 700K has happened.]
>
> Storing the XML as a file and then reading it into CF using CFFILE results
> could result in 1.4 Mb conversation; reading it directly - if possible - cuts
> that conversation by half.
>
> That's my goal. It would be the exact opposite of a cfhttp tag.
>
> Thanks.
>
>

What happens if you POST the data, rather then GET the data. I.E.
something like: 'ajax('POST',myURL,true)'. I have no idea what your
home grown 'ajax()' function exactly does. But I know it is trival to
have ajax submit a post request rather then a get request.

My current applicaiton does it in this manner:

<cfajaxproxy cfc="services.purDAO" jsclassname="purDAO">

...

var updatePUR = function()
{
var purDAOproxy = new purDAO();
purDAOproxy.setHTTPMethod('post');
purDAOproxy.setCallbackHandler(populateValidateDiv);
purDAOproxy.setErrorHandler(myErrorHandler);

purDAOproxy.setForm('edit');
purDAOproxy.updatePUR('#form.use_Number#',purYear,currentPUR,false);

return false;
}

This relies on CF8's ajax framework, but it should not be hard to
replicate if you do not want to use the built in one.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

> What happens if you POST the data, rather then GET the data. I.E.
> something like: 'ajax('POST',myURL,true)'. I have no idea what your
> home grown 'ajax()' function exactly does. But I know it is trivial to
> have ajax submit a post request rather then a get request.

"ajax()" as a cross-browser, multi-purpose XmlHttpRequest function. Its primary purpose is to limit thread use due to bandwidth issues. [It's single-threaded.]

A 4th parameter - not shown above - routes the output from the function to other purpose-specific JS functions most of which parse different XML streams. It probably equates to your "setCallbackHandler".

Anyway...

Constructs not available in CF7 are - at least for now - not allowed. CF8 is currently being tested on the development server, but production is CF7.

I do like your solution, though. I'll see if I can replicate something similar in CF7.

Thanks.




Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

coffeedrinker56 wrote:
> I do like your solution, though. I'll see if I can replicate something similar
> in CF7.

A suggestion, in case you do not think of it yet. If you have access to
the CF8 server, you could inspect the javascript created by the
<cfajaxproxy...> tag.

It just creates some 'out of the box' JS in the response that can be
inspected in the browser. I suspect somebody experience in JS and AJAX
would be able to use it as a template if not a whole sale copy and paste.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2008 Mar 04, 2008

Copy link to clipboard

Copied

you can also use (rob gonda's?) ajaxCFC with cfmx 7 to achieve similar
functionality.
many recent js frameworks support/include such functionality, too.


Azadi Saryev
Sabai-dee.com
http://www.sabai-dee.com/

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guest
Mar 05, 2008 Mar 05, 2008

Copy link to clipboard

Copied

LATEST
Ian, et al:

Writing a custom Ajax function in JS is simple as well. This one is pretty "generic" excepting that it always expects incoming responses as XML.

Note: The "setPostData" function is a form scraper. It retrieves all non-zero, non-null form value pairs from the RIA - reflecting the curent DOM status - and formats it as XML.

function ajax( method, url, async, filetype) {
var myMethod = method; // 'GET', 'POST', or null
var myURL = url; // script to be executed
var myAsync = async; // true=asynchronous, false=synchronous
var myType = filetype; // flag used for routing after data are loaded
var mySend = null; // default value is null - for GET method
ajaxAvailable = false; //global flag stops process interruption
if (myMethod == "") {
myMethod = 'GET'; // set default method
} else if (myMethod == 'POST') {
mySend = setPostData(); // If post, load data to be posted
}
if (myAsync == "") {
myAsync = true; // default is asynchronous
}
if (myType == "") {
myType = 'SA'; // default data type used for data parsing
}

// Instantiate XmlHttpRequest object. ("ajaxHttp" is global)
try { ajaxHttp = new XMLHttpRequest();
} catch ( err ) {
try { ajaxHttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch ( err ) {
try { ajaxHttp = new ActiveXObject("MSXML4.XMLHTTP");
} catch ( err ) {
try { ajaxHttp = new ActiveXObject("MSXML3.XMLHTTP");
} catch ( err ) {
// reroute for non-ajax-capable browsers
document.location.href = 'wit2_bad_browser.cfm';
}
}
}
}
try { ajaxHttp.overridemimetype('text/xml'); // forced mime type
ajaxHttp.onerror = function() {
document.getElementById("message").innerHTML = 'Load Error';
}
} catch ( err ) {};
ajaxHttp.onreadystatechange = function ( aEvt ) {
window.status = 'Loading ' + filetype + ' data...';
// If process is not complete ...
if ( ajaxHttp.readystate < 4 ) {
return;
} else {
window.status = 'Done.';
if (ajaxHttp.status == 200) {
// loads global "ajaxDoc" with XML
ajaxDoc = ajaxHttp.responseXML;
// route to the appropriate XML data handler
loadDocs( myType );
} else {
// Otherwise, report error
myTarget.setAttribute("style", "color:#ff0000");
myTarget.innerHTML = 'Error code ' + ajaxHttp.status + ': Unable to load the ' + filetype + ' data file.';
}
}
}

// initiate the request
ajaxHttp.open( myMethod, myURL, myAsync );
// sends null for GET method, data for POST method
ajaxHttp.send( mySend );
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation