Entry
How can post XML data to the server?
How can I receive XML data from the server?
Sep 5th, 2004 07:08
Martin Honnen, http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/xmmscXML.asp
IE5+ on Win and NN6+ offer JavaScript support to create XML DOM
documents and to post such a document to the server and process the
response from the server (which can again be an XML document).
The following example HTML page contains IE5+/Win and NN6+, Mozilla,
Firefox, and hopefully Opera 7.60+ implementations for three functions:
createXMLFromString: parses string and creates XML DOM document
serializeXML: serializes XML DOM document to string
postXML: posts an XML DOM document to server and receive response
The last script block in that page contains examples on how to use the
functions, obivously the posting to a server can only be tested if you
set up some server side ASP or PHP (or other server side processing)
page to receive the XML data as the body of an HTTP POST request and
to send some XML document back as the body of an HTTP response.
Please note that there are two ways to perform a HTTP POST request, you
can do it synchronously and you can do it asynchronously, the first
example below does it synchronously which is a bit easier to script and
choosen here first as it is easier to follow what is happening. However
synchronous requests have a big disdavantage, the browser is likely
blocked while the requests is being sent and the response is being
received so in a real web application you should use asynchronous
requests and therefore at the end there is an example using an
asynchronous requests.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>
XML parsing, serialization, HTTP POST data exchange
</title>
<script type="text/javascript">
/* dummy implementations for those browsers not having XML support */
function createXMLFromString (string) {
output('XML not implemented.');
return null;
}
function serializeXML (xmlDocument) {
output('XML not implemented.');
return '';
}
function postXML (url, xmlDocument) {
output('XML not implemented.');
return null;
}
function output (text) {
var p, layer;
if (document.createElement && (p = document.createElement('p'))) {
p.appendChild(document.createTextNode(text));
document.body.appendChild(p);
}
else if (typeof Layer != 'undefined' && (layer = new
Layer(window.innerWidth))) {
layer.top = document.height;
layer.left = 0;
layer.document.open();
layer.document.write('<p>' + text + '<\/p>');
layer.document.close();
layer.visibility = 'show';
document.height += layer.clip.height;
}
}
</script>
<script type="text/jscript">
function createXMLFromString (string) {
var xmlDocument;
try {
xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
xmlDocument.async = false;
xmlDocument.loadXML(string);
return xmlDocument;
}
catch (e) {
output("Can't create XML document.");
return null;
}
}
function serializeXML (xmlDocument) {
return xmlDocument.xml;
}
function postXML (url, xmlDocument) {
var httpRequest;
try {
httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
httpRequest.open('POST', url, false);
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document.");
return null;
}
}
</script>
<script type="text/javascript; version=1.5">
function createXMLFromString (string) {
var xmlParser, xmlDocument;
try {
xmlParser = new DOMParser();
xmlDocument = xmlParser.parseFromString(string, 'text/xml');
return xmlDocument;
}
catch (e) {
output("Can't create XML document.");
return null;
}
}
function serializeXML (xmlDocument) {
var xmlSerializer;
try {
xmlSerializer = new XMLSerializer();
return xmlSerializer.serializeToString(xmlDocument);
}
catch (e) {
output("Can't serialize XML document.");
return '';
}
}
function postXML (url, xmlDocument) {
try {
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', url, false);
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document");
return null;
}
}
</script>
<script type="text/javascript">
/* Here starts the code to perform some tests with the script functions
defined above.
*/
function testXMLDocumentCreationFromString () {
var xmlDocument =
createXMLFromString('<gods><god name="Kibo" \/><\/gods>');
if (xmlDocument) {
output('Parsing from string results in: ' + xmlDocument);
output('xmlDocument.documentElement.nodeName: ' +
xmlDocument.documentElement.nodeName);
var xibo = xmlDocument.createElement('god');
xibo.setAttribute('name', 'Xibo');
xmlDocument.documentElement.appendChild(xibo);
output(
'xmlDocument.documentElement.lastChild.getAttribute("name"): ' +
xmlDocument.documentElement.lastChild.getAttribute("name"));
}
return xmlDocument;
}
function testXMLDocumentSerialization (xmlDocument) {
if (xmlDocument) {
output(xmlDocument + ' serialized has markup: ' +
serializeXML(xmlDocument));
}
}
function testXMLPosting (url, xmlDocument) {
if (xmlDocument) {
var httpRequest = postXML(url, xmlDocument);
output('Trying to HTTP POST ' + xmlDocument + ' to ' + url +
' results in: ' + httpRequest);
if (httpRequest) {
output('HTTP response status: ' + httpRequest.status);
output('Response as text: ' + httpRequest.responseText);
output('responseXML.documentElement.nodeName: ' +
httpRequest.responseXML.documentElement.nodeName);
}
}
}
window.onload = function (evt) {
var xmlDocument = testXMLDocumentCreationFromString();
testXMLDocumentSerialization(xmlDocument);
testXMLPosting('xmlDataExchangeReflect.asp', xmlDocument);
};
</script>
</head>
<body>
<h1>XML parsing, serialization, HTTP POST data exchange</h1>
</body>
</html>
The page has been tested to work with IE 5, IE 5.5, IE 6 (all on
Windows), with Mozilla 1.0 and later, Netscape 7, Firefox 0.9.
With older browsers like Netscape 4 not supporting XML (parsing,
serialization, data exchange) the code degrades gracefully by not
throwing an error but but allowing your script to handle that case, in
the example a message is shown that XML is not supported.
Here is a simple ASP JScript page which simply receives a HTTP POST
request with a XML file in the request body and then sends that file
back to the client, in the case that the body of the HTTP POST request
can not be parsed as XML some error details are written back to the client:
<%@ Language="JScript" %>
<%
/* for a simple test/demonstration this page simply parses the posted XML,
attaches a date/time stamp as server-date attribute on the root element
and serializes it back to the client
*/
var receivedXML = Server.CreateObject('Msxml2.DOMDocument.4.0');
receivedXML.async = false;
var loaded = receivedXML.load(Request);
if (loaded) {
Response.ContentType = 'text/xml';
receivedXML.documentElement.setAttribute('server-date', new
Date().toUTCString());
receivedXML.save(Response);
}
else {
var parseError = receivedXML.parseError;
Response.Write('<p>Parsing error: ' + parseError.reason +
' for line: ' + parseError.line + ' at position: ' +
parseError.linepos +
' at file position: ' + parseError.filepos +
' with source text: ' + Server.HTMLEncode(parseError.srcText) +
' ; HTTP Content-Type: ' +
Request.ServerVariables('HTTP_CONTENT_TYPE') +
'; HTTP Content-Length: ' +
Request.ServerVariables('HTTP_CONTENT_LENGTH') + '.<\/p>\r\n');
}
%>
Here is the promised code and example for doing asynchronous requests,
you have to use the onreadystatechange event handler and check the
readyState being 4 before you can process the response:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>
XML parsing, serialization, asynchronous HTTP POST data exchange
</title>
<script type="text/javascript">
/* dummy implementations for those browsers not having XML support */
function createXMLFromString (string) {
output('XML not implemented.');
return null;
}
function serializeXML (xmlDocument) {
output('XML not implemented.');
return '';
}
function postXML (url, xmlDocument) {
output('XML not implemented.');
return null;
}
function output (text) {
var p, layer;
if (document.createElement && (p = document.createElement('p'))) {
p.appendChild(document.createTextNode(text));
document.body.appendChild(p);
}
else if (typeof Layer != 'undefined' && (layer = new
Layer(window.innerWidth))) {
layer.top = document.height;
layer.left = 0;
layer.document.open();
layer.document.write('<p>' + text + '<\/p>');
layer.document.close();
layer.visibility = 'show';
document.height += layer.clip.height;
}
}
</script>
<script type="text/jscript">
function createXMLFromString (string) {
var xmlDocument;
try {
xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
xmlDocument.async = false;
xmlDocument.loadXML(string);
return xmlDocument;
}
catch (e) {
output("Can't create XML document.");
return null;
}
}
function serializeXML (xmlDocument) {
return xmlDocument.xml;
}
function postXML (url, xmlDocument, responseHandler) {
var httpRequest;
try {
httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
httpRequest.open('POST', url, true);
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4) {
responseHandler(httpRequest);
}
};
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document.");
return null;
}
}
</script>
<script type="text/javascript; version=1.5">
function createXMLFromString (string) {
var xmlParser, xmlDocument;
try {
xmlParser = new DOMParser();
xmlDocument = xmlParser.parseFromString(string, 'text/xml');
return xmlDocument;
}
catch (e) {
output("Can't create XML document.");
return null;
}
}
function serializeXML (xmlDocument) {
var xmlSerializer;
try {
xmlSerializer = new XMLSerializer();
return xmlSerializer.serializeToString(xmlDocument);
}
catch (e) {
output("Can't serialize XML document.");
return '';
}
}
function postXML (url, xmlDocument, responseHandler) {
try {
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', url, true);
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4) {
responseHandler(httpRequest);
}
};
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document");
return null;
}
}
</script>
<script type="text/javascript">
/* Here starts the code to perform some tests with the script functions
defined above.
*/
function testXMLDocumentCreationFromString () {
var xmlDocument =
createXMLFromString('<gods><god name="Kibo" \/><\/gods>');
if (xmlDocument) {
output('Parsing from string results in: ' + xmlDocument);
output('xmlDocument.documentElement.nodeName: ' +
xmlDocument.documentElement.nodeName);
var xibo = xmlDocument.createElement('god');
xibo.setAttribute('name', 'Xibo');
xmlDocument.documentElement.appendChild(xibo);
output(
'xmlDocument.documentElement.lastChild.getAttribute("name"): ' +
xmlDocument.documentElement.lastChild.getAttribute("name"));
}
return xmlDocument;
}
function testXMLDocumentSerialization (xmlDocument) {
if (xmlDocument) {
output(xmlDocument + ' serialized has markup: ' +
serializeXML(xmlDocument));
}
}
function exampleResponseHandler (httpRequest) {
output('HTTP response status: ' + httpRequest.status);
output('Response as text: ' + httpRequest.responseText);
output('responseXML.documentElement.nodeName: ' +
httpRequest.responseXML.documentElement.nodeName);
}
function testXMLPosting (url, xmlDocument, responseHandler) {
if (xmlDocument) {
var httpRequest = postXML(url, xmlDocument, responseHandler);
output('Trying to HTTP POST ' + xmlDocument + ' to ' + url +
' results in: ' + httpRequest);
}
}
window.onload = function (evt) {
var xmlDocument = testXMLDocumentCreationFromString();
testXMLDocumentSerialization(xmlDocument);
testXMLPosting('xmlDataExchangeReflect.asp', xmlDocument,
exampleResponseHandler);
};
</script>
</head>
<body>
<h1>XML parsing, serialization, asynchronous HTTP POST data exchange</h1>
</body>
</html>
Other browsers like Safari since version 1.2 or Opera since version 7.60
are trying to catch up with IE/Win and Mozilla and implement
XMLHttpRequest too. So far Safari 1.2 doesn't implement DOMParser or
offer any other way to parse some XML markup into a DOM document, it has
a bug that document.implementation.createDocument('', 'tagName', null)
creates a document but doesn't add the documentElement element, but
besides that you can use Safari 1.2 to create an XML document and post
it to the server as in the following example:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>
asynchronous XML HTTP POST data exchange
</title>
<script type="text/javascript">
/* dummy implementations for those browsers not having XML support */
function createXMLDocumentWithRootElement (tagName) {
output('XML not implemented.');
return null;
}
function serializeXML (xmlDocument) {
output('XML not implemented.');
return '';
}
function postXML (url, xmlDocument) {
output('XML not implemented.');
return null;
}
function output (text) {
var p, layer;
if (document.createElement && (p = document.createElement('p'))) {
p.appendChild(document.createTextNode(text));
document.body.appendChild(p);
}
else if (typeof Layer != 'undefined' && (layer = new
Layer(window.innerWidth))) {
layer.top = document.height;
layer.left = 0;
layer.document.open();
layer.document.write('<p>' + text + '<\/p>');
layer.document.close();
layer.visibility = 'show';
document.height += layer.clip.height;
}
}
</script>
<script type="text/jscript">
function createXMLDocumentWithRootElement (tagName) {
var xmlDocument;
try {
xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
xmlDocument.appendChild(xmlDocument.createElement(tagName));
return xmlDocument;
}
catch (e) {
return null;
}
}
function serializeXML (xmlDocument) {
return xmlDocument.xml;
}
function postXML (url, xmlDocument, responseHandler) {
var httpRequest;
try {
httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
httpRequest.open('POST', url, true);
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4) {
responseHandler(httpRequest);
}
};
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document.");
return null;
}
}
</script>
<script type="text/javascript; version=1.5">
function createXMLDocumentWithRootElement (tagName) {
var xmlDocument;
if (document.implementation && document.implementation.createDocument &&
(xmlDocument = document.implementation.createDocument('', tagName,
null))) {
if (xmlDocument.documentElement == null) { // Safari 1.2 bug
// add documentElement
xmlDocument.appendChild(xmlDocument.createElement(tagName));
}
return xmlDocument;
}
else {
return null;
}
}
function serializeXML (xmlDocument) {
var xmlSerializer;
try {
xmlSerializer = new XMLSerializer();
return xmlSerializer.serializeToString(xmlDocument);
}
catch (e) {
output("Can't serialize XML document.");
return '';
}
}
function postXML (url, xmlDocument, responseHandler) {
try {
var httpRequest = new XMLHttpRequest();
httpRequest.open('POST', url, true);
// work around Safari 1.2 bug that Safari doesn't set the Content-Type
// to text/xml
if (httpRequest.setRequestHeader) {
httpRequest.setRequestHeader('Content-Type', 'text/xml');
}
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4) {
responseHandler(httpRequest);
}
};
httpRequest.send(xmlDocument);
return httpRequest;
}
catch (e) {
output("Can't post XML document");
return null;
}
}
</script>
<script type="text/javascript">
/* Here starts the code to perform some tests with the script functions
defined above.
*/
function testXMLDocumentCreation () {
var xmlDocument = createXMLDocumentWithRootElement('gods');
if (xmlDocument) {
var god = xmlDocument.createElement('god');
god.appendChild(xmlDocument.createTextNode('Kibo'));
xmlDocument.documentElement.appendChild(god);
}
else {
output('Can\'t create XML document.');
}
return xmlDocument;
}
function testXMLDocumentSerialization (xmlDocument) {
if (xmlDocument) {
var serializedXML = serializeXML(xmlDocument);
if (serializedXML) {
output(xmlDocument + ' serialized has markup: ' +
serializeXML(xmlDocument));
}
}
}
function exampleResponseHandler (httpRequest) {
output('HTTP response status: ' + httpRequest.status);
output('Response as text: ' + httpRequest.responseText);
output('responseXML.documentElement.nodeName: ' +
httpRequest.responseXML.documentElement.nodeName);
}
function testXMLPosting (url, xmlDocument, responseHandler) {
if (xmlDocument) {
var httpRequest = postXML(url, xmlDocument, responseHandler);
output('Trying to HTTP POST ' + xmlDocument + ' to ' + url +
' results in: ' + httpRequest);
}
}
window.onload = function (evt) {
var xmlDocument = testXMLDocumentCreation();
testXMLDocumentSerialization(xmlDocument);
testXMLPosting('xmlDataExchangeReflect.aspx', xmlDocument,
exampleResponseHandler);
};
</script>
</head>
<body>
<h1>XML creation, serialization, asynchronous HTTP POST data exchange</h1>
</body>
</html>