Unable to parse XML in Chrome/Opera/Safari - javascript

I am getting the following response from a SOAP webservice, which I need to parse for displaying data in a HTML page
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<ExecuteResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
<ExecuteResult i:type="b:RetrieveUserPrivilegesResponse" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:b="http://schemas.microsoft.com/crm/2011/Contracts">
<a:ResponseName>RetrieveUserPrivileges</a:ResponseName>
<a:Results xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
<a:KeyValuePairOfstringanyType>
<c:key>RolePrivileges</c:key>
<c:value i:type="b:ArrayOfRolePrivilege">
<b:RolePrivilege>
<b:BusinessUnitId>e09f3de8-925d-e311-8a5d-000c299c86a3</b:BusinessUnitId>
<b:Depth>Global</b:Depth>
<b:PrivilegeId>b7a1f52a-b8a9-11d8-84ab-0007e9e100cc</b:PrivilegeId>
</b:RolePrivilege>
<b:RolePrivilege>
<b:BusinessUnitId>e09f3de8-925d-e311-8a5d-000c299c86a3</b:BusinessUnitId>
<b:Depth>Global</b:Depth>
<b:PrivilegeId>655e4282-b8a9-11d8-84ab-0007e9e100cc</b:PrivilegeId>
</b:RolePrivilege>
<b:RolePrivilege>
<b:BusinessUnitId>e09f3de8-925d-e311-8a5d-000c299c86a3</b:BusinessUnitId>
<b:Depth>Global</b:Depth>
<b:PrivilegeId>98b5ccb2-b8a9-11d8-84ab-0007e9e100cc</b:PrivilegeId>
</b:RolePrivilege>
</c:value>
</a:KeyValuePairOfstringanyType>
</a:Results>
</ExecuteResult>
</ExecuteResponse>
</s:Body>
</s:Envelope>
Following is the piece of code I am using to retrieve the <b:BusinessUnitId> tag values. The input to the functions are resultXml which is the XML above and attributeName which I am passing as "b:PrivilegeId".
function extractValuesFromXml(resultXml, attributeName)
{
var valueArray = new Array();
var parseXml;
if (typeof window.DOMParser != "undefined")
{
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
}
else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM"))
{
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
}
else
{
throw new Error("No XML parser found");
}
var xmlDoc = parseXml(resultXml);
x = xmlDoc.getElementsByTagName(attributeName);
for (i = 0; i < x.length; i++)
{
if (x[i].childNodes[0] != null && x[i].childNodes[0] != 'undefined' && x[i].childNodes[0].data != null && x[i].childNodes[0].data != 'undefined')
{
valueArray[i] = x[i].childNodes[0].data.toUpperCase();;
}
}
return valueArray;
}
The code works perfectly in IE and Firefox, but I can't seem to get it to work in Chrome, Opera or Safari. I have tried all sorts of things to have this working in these 3 browsers but have failed.
Any help would be appreciated! Thanks.

Well, finally got it to work. IE and Firefox could use the getElementsByTagName("b:PrivilegeId") but Chrome, Opera and Safari could use getElementsByTagName("Privilege").
So, I used this wonderful library here : http://jsfiddle.net/pupunzi/dnJNS/ to detect the browser and modify the code. And now it works like a charm!
My code now looks like the following:
function extractValuesFromXml(resultXml)
{
var valueArray = new Array();
var parseXml;
if (typeof window.DOMParser != "undefined")
{
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
}
else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM"))
{
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
}
else
{
throw new Error("No XML parser found");
}
var xmlDoc = parseXml(resultXml);
if($.browser.msie == true || $.browser.mozilla == true)
{
x = xmlDoc.getElementsByTagName("b:PrivilegeId");
}
else
{
x = xmlDoc.getElementsByTagName("PrivilegeId");
}
for (i = 0; i < x.length; i++)
{
if (x[i].childNodes[0] != null && x[i].childNodes[0] != 'undefined' && x[i].childNodes[0].data != null && x[i].childNodes[0].data != 'undefined')
{
valueArray[i] = x[i].childNodes[0].data.toUpperCase();;
}
}
return valueArray;
}

Related

Interaction in a Dynamic action between javascript and plsql tasks

I'm trying to execute several pl/sql blocks in a Dynamic Action, with feedback to the end user with a modal dialog reporting the current satus.
Something like:
Processing Step 1...
/*Run pl/sql code for step 1*/
Processing Step 2...
/*Run pl/sql code for Step 2*/
and so on...
Both, the pl/sql and javascript code, run as intended but when I combined them on a Dynamic Action in the sequence:
1 - Execute Javascript
2 - Execute PL/SQL block /* With wait for result option checked*/
3 - Execute Javascript
4 - Execute PL/SQL block
The status dialog is not been shown, however the pl/sql blocks are completed without problems.
I realize that this must be something related to javascript not been multithreaded, so I've moved the pl/sql block to application processes and run them as ajax calls like this:
function something(){
var get;
var result = 0;
updateStatus('Running Step1');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
result = get.get();
if(result > 0){
updateStatus('Running Step 2');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
result = get.get();
}
closeStatusDialog();
}
But still, as before, the processes run fine but the dialog doesn't appear. Finally I added a setTimeOut function to each call, like this:
function something(){
var get;
var result = 0;
updateStatus('Running Step1');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
result = setTimeOut(get.get(),500);
if(result > 0){
updateStatus('Running Step 2');
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
result = setTimeOut(get.get(),500);
}
closeStatusDialog();
}
But still nothing. What can I do to get this running as needed?.
I've checked the browser console and no exeptions are been thrown, likewise with the pl/sql blocks.
I've solved it, although the solution doesn't rely on dynamic actions, just javascript and applicacion processes. I'm posting this for anyone with a similar problem.
The htmldb_Get Javascript object is an oracle-apex wrapper for the XMLHttpRequest AJAX object. Poorly documented though.
I've found a copy of the code (at the bottom) and it turns out it has another function called GetAsync that allows to pass a function as a parameter to asign it to the onreadystatechange attribute on the XMLHttpRequest object, which will be executed each time the attribute readyState of the underlying XMLHttpRequest changes.
The function passed as a parameter can't have parameters on its own definition.
So, instead of calling get() on the htmldb_Get object you need to call GetAsync(someFunction)
With this solution in my case:
function something(){
var get;
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_1',0);
get.GetAsync(someFunctionStep1);
}
function someFunctionStep1(){
if(p.readyState == 0){ /*p is the underlying XMLHttpRequest object*/
console.log("request not initialized");
updateStatus('Running Step 1');
} else if(p.readyState == 1){
console.log("server connection established");
} else if(p.readyState == 2){
console.log("request received");
} else if(p.readyState == 3){
console.log("processing request");
} else if(p.readyState == 4){
console.log("request finished and response is ready");
callStep2();
}
}
function callStep2(){
var get;
get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=P6_STEP_2',0);
get.GetAsync(someFunctionStep2);
}
function someFunctionStep2(){
if(p.readyState == 0){
console.log("request not initialized");
updateStatus('Running Step 2');
} else if(p.readyState == 1){
console.log("server connection established");
} else if(p.readyState == 2){
console.log("request received");
} else if(p.readyState == 3){
console.log("processing request");
} else if(p.readyState == 4){
console.log("request finished and response is ready");
closeDialog();
}
}
Here's the htmldb_get definition, at the end is the GetAsync function
/*
str should be in the form of a valid f?p= syntax
*/
function htmldb_Get(obj,flow,req,page,instance,proc,queryString) {
//
// setup variables
//
this.obj = $x(obj); // object to put in the partial page
this.proc = proc != null ? proc : 'wwv_flow.show'; // proc to call
this.flow = flow != null ? flow : $x('pFlowId').value; // flowid
this.request = req != null ? req : ''; // request
this.page = page; // page
this.params = ''; // holder for params
this.response = ''; // holder for the response
this.base = null; // holder fot the base url
this.queryString = queryString!= null ? queryString : null ; // holder for passing in f? syntax
this.syncMode = false;
//
// declare methods
//
this.addParam = htmldb_Get_addParam;
this.add = htmldb_Get_addItem;
this.getPartial = htmldb_Get_trimPartialPage;
this.getFull = htmldb_Get_fullReturn;
this.get = htmldb_Get_getData;
this.url = htmldb_Get_getUrl;
this.escape = htmldb_Get_escape;
this.clear = htmldb_Get_clear;
this.sync = htmldb_Get_sync;
this.setNode = setNode;
this.replaceNode = replaceNode
//
// setup the base url
//
var u = window.location.href.indexOf("?") > 0 ?
window.location.href.substring(0,window.location.href.indexOf("?"))
: window.location.href;
this.base = u.substring(0,u.lastIndexOf("/"));
if ( this.proc == null || this.proc == "" )
this.proc = u.substring(u.lastIndexOf("/")+1);
this.base = this.base +"/" + this.proc;
//
// grab the instance form the page form
//
if ( instance == null || instance == "" ) {
var pageInstance = document.getElementById("pInstance");
if ( typeof(pageInstance) == 'object' ) {
this.instance = pageInstance.value;
}
} else {
this.instance = instance;
}
//
// finish setiing up the base url and params
//
if ( ! queryString ) {
this.addParam('p_request', this.request) ;
this.addParam('p_instance', this.instance);
this.addParam('p_flow_id', this.flow);
this.addParam('p_flow_step_id',this.page);
}
function setNode(id) {
this.node = html_GetElement(id);
}
function replaceNode(newNode){
var i=0;
for(i=this.node.childNodes.length-1;i>=0;i--){
this.node.removeChild(this.node.childNodes[i]);
}
this.node.appendChild(newNode);
}
}
function htmldb_Get_sync(s){
this.syncMode=s;
}
function htmldb_Get_clear(val){
this.addParam('p_clear_cache',val);
}
//
// return the queryString
//
function htmldb_Get_getUrl(){
return this.queryString == null ? this.base +'?'+ this.params : this.queryString;
}
function htmldb_Get_escape(val){
// force to be a string
val = val + "";
val = val.replace(/\%/g, "%25");
val = val.replace(/\+/g, "%2B");
val = val.replace(/\ /g, "%20");
val = val.replace(/\./g, "%2E");
val = val.replace(/\*/g, "%2A");
val = val.replace(/\?/g, "%3F");
val = val.replace(/\\/g, "%5C");
val = val.replace(/\//g, "%2F");
val = val.replace(/\>/g, "%3E");
val = val.replace(/\</g, "%3C");
val = val.replace(/\{/g, "%7B");
val = val.replace(/\}/g, "%7D");
val = val.replace(/\~/g, "%7E");
val = val.replace(/\[/g, "%5B");
val = val.replace(/\]/g, "%5D");
val = val.replace(/\`/g, "%60");
val = val.replace(/\;/g, "%3B");
val = val.replace(/\?/g, "%3F");
val = val.replace(/\#/g, "%40");
val = val.replace(/\&/g, "%26");
val = val.replace(/\#/g, "%23");
val = val.replace(/\|/g, "%7C");
val = val.replace(/\^/g, "%5E");
val = val.replace(/\:/g, "%3A");
val = val.replace(/\=/g, "%3D");
val = val.replace(/\$/g, "%24");
//val = val.replace(/\"/g, "%22");
return val;
}
//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addParam(name,val){
if ( this.params == '' )
this.params = name + '='+ ( val != null ? this.escape(val) : '' );
else
//this.params = this.params + '&'+ name + '='+ ( val != null ? val : '' );
this.params = this.params + '&'+ name + '='+ ( val != null ? this.escape(val) : '' );
return;
}
//
// Simple function to add name/value pairs to the url
//
function htmldb_Get_addItem(name,value){
this.addParam('p_arg_names',name);
this.addParam('p_arg_values',value);
}
//
// funtion strips out the PPR sections and returns that
//
function htmldb_Get_trimPartialPage(startTag,endTag,obj) {
setTimeout(html_processing,1);
if (obj) {this.obj = $x(obj);}
if (!startTag){startTag = '<!--START-->'};
if (!endTag){endTag = '<!--END-->'};
var start = this.response.indexOf(startTag);
var part;
if ( start >0 ) {
this.response = this.response.substring(start+startTag.length);
var end = this.response.indexOf(endTag);
this.response = this.response.substring(0,end);
}
if ( this.obj ) {
if(this.obj.nodeName == 'INPUT'){
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
}else{
this.obj.value = this.response;
}
}else{
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
}else{
this.obj.innerHTML = this.response;
}
}
}
//window.status = 'Done'
setTimeout(html_Doneprocessing,1);
return this.response;
}
var gResult = null;
var gNode = null
function htmldb_get_WriteResult(){
if(gNode && ( gNode.nodeName == 'INPUT' || gNode.nodeName == 'TEXTAREA')){
gNode.value = gResult;
}else{
gNode.innerHTML = gResult;
}
gResult = null;
gNode = null;
return;
}
//
// function return the full response
//
function htmldb_Get_fullReturn(obj) {
setTimeout(html_processing,1);
if (obj) { this.obj = html_GetElement(obj);}
if ( this.obj ) {
if(this.obj.nodeName == 'INPUT'){
this.obj.value = this.response;
}else{
if(document.all){
gResult = this.response;
gNode = this.obj;
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,10);
}else{
this.obj.innerHTML = this.response;
}
}
}
setTimeout(html_Doneprocessing,1);
return this.response;
}
//
// Perform the actual get from the server
//
function htmldb_Get_getData(mode,startTag,endTag){
html_processing();
var p;
try {
p = new XMLHttpRequest();
} catch (e) {
p = new ActiveXObject("Msxml2.XMLHTTP");
}
try {
var startTime = new Date();
p.open("POST", this.base, this.syncMode);
p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
p.send(this.queryString == null ? this.params : this.queryString );
this.response = p.responseText;
if ( this.node )
this.replaceNode(p.responseXML);
if ( mode == null || mode =='PPR' ) {
return this.getPartial(startTag,endTag);
} if ( mode == "XML" ) {
setTimeout(html_Doneprocessing,1);
return p.responseXML;
} else {
return this.getFull();
}
} catch (e) {
setTimeout(html_Doneprocessing,1);
return;
}
}
function html_Doneprocessing(){
document.body.style.cursor="default";
}
function html_processing(){
document.body.style.cursor="wait";
}
/*
this adds better aysnc functionality
to the htmldb_Get object
pVar is the function that you want to call when the xmlhttp state changes
in the function specified by pVar the xmlhttp object can be referenced by the variable p
*/
htmldb_Get.prototype.GetAsync = function(pVar){
try{
p = new XMLHttpRequest();
}catch(e){
p = new ActiveXObject("Msxml2.XMLHTTP");
}
try {
var startTime = new Date();
p.open("POST", this.base, true);
if(p) {
p.onreadystatechange = pVar;
p.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
p.send(this.queryString == null ? this.params : this.queryString );
return p;
}
}catch(e){
return false;
}
}
/* PDF OUTPUT */
/*Gets PDF src XML */
function htmldb_ExternalPost(pThis,pRegion,pPostUrl){
var pURL = 'f?p='+html_GetElement('pFlowId').value+':'+html_GetElement('pFlowStepId').value+':'+html_GetElement('pInstance').value+':FLOW_FOP_OUTPUT_R'+pRegion
document.body.innerHTML = document.body.innerHTML + '<div style="display:none;" id="dbaseSecondForm"><form id="xmlFormPost" action="' + pPostUrl + '?ie=.pdf" method="post" target="pdf"><textarea name="vXML" id="vXML" style="width:500px;height:500px;"></textarea></form></div>';
var l_El = html_GetElement('vXML');
var get = new htmldb_Get(l_El,null,null,null,null,'f',pURL.substring(2));
get.get();
get = null;
setTimeout('html_GetElement("xmlFormPost").submit()',10);
return;
}
function $xml_Control(pThis){
this.xsl_string = '<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:output method="html"/><xsl:param name="xpath" /><xsl:template match="/"><xsl:copy-of select="//*[#id=$xpath]"/></xsl:template></xsl:stylesheet>';
if(document.all){
this.xsl_object = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
this.xsl_object.async=false;
this.xsl_object.loadXML(this.xsl_string)
tmp = new ActiveXObject("Msxml2.XSLTemplate.3.0");
tmp.stylesheet = this.xsl_object;
this.xsl_processor = tmp.createProcessor();
}else{
this.xsl_object = (new DOMParser()).parseFromString(this.xsl_string, "text/xml");
this.xsl_processor = (new XSLTProcessor());
this.xsl_processor.importStylesheet(this.xsl_object);
this.ownerDocument = document.implementation.createDocument("", "test", null);
}
this.xml = pThis;
this.CloneAndPlace = _CloneAndPlace;
return
function _CloneAndPlace(pThis,pThat,pText){
var lThat = $x(pThat);
if(document.all){
this.xsl_processor.addParameter("xpath", pThis);
this.xsl_processor.input = this.xml;
this.xsl_processor.transform;
var newFragment = this.xsl_processor.output;
}else{
this.xsl_processor.setParameter(null, "xpath", pThis);
var newFragment = this.xsl_processor.transformToFragment(this.xml,this.ownerDocument);
}
if(lThat){
if(document.all){
lThat.innerHTML='';
lThat.innerHTML=newFragment;
}else{
lThat.innerHTML='';
lThat.appendChild(newFragment);
}
/*
in IE newFragment will be a string
in FF newFragment will be a dome Node (more useful)
*/
return newFragment;
}
}
}

Adding XML element using Jquery

I have been working on adding XML element to XML structure without success, here is my code.
var parseXml;
if (window.DOMParser) {
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
}
else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) {
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
}
else {
parseXml = function() { return null; }
}
var xmlTree = parseXml("<root></root>");
function add_children(child_name,parent_name)
{
str = '<'+child_name+'></'+child_name+'>';
//strXML = parseXml(str);
$(xmlTree).find(parent_name).append(str);
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
console.log(xmlString);
}
add_children("apple","root");
add_children("orange","root");
add_children("lychee","root");
but console is showing <root/> all three times
The problem is that you are creating the node in the Html document, not in the XML one, so you can't append it. Change this line:
str = '<'+child_name+'></'+child_name+'>';
For this one:
str = xmlTree.createElement(child_name);
See the working code in http://jsfiddle.net/W9Wpb/

construct xml string from parsed xml

My code for parsexml:
var parseXml = function (xml) {
var dom = null;
if (window.DOMParser) {
try {
dom = (new DOMParser()).parseFromString(xml, "text/xml");
}
catch (e) { dom = null; }
}
else if (window.ActiveXObject) {
try {
dom = new ActiveXObject('Microsoft.XMLDOM');
dom.async = false;
if (!dom.loadXML(xml)) // parse error ..
window.alert(dom.parseError.reason + dom.parseError.srcText);
}
catch (e) { dom = null; }
}
else
alert("cannot parse xml string!");
return dom;
}
now suppose
s="<a>random</a>";
b=parseXml(s);
now I want to get s back from b. How do I do that?
You need an XMLSerializer in most browsers and the xml property of XML nodes in older version of IE:
function serializeXmlNode(xmlNode) {
if (typeof window.XMLSerializer != "undefined") {
return new window.XMLSerializer().serializeToString(xmlNode);
} else if (typeof xmlNode.xml != "undefined") {
return xmlNode.xml;
}
return "";
}
var xmlStr = serializeXmlNode(b);
You need a XMLSerializer (MDN docu) object for converting your XML tree back to a string:
var ser = new XMLSerializer();
s = ser.serializeToString( b );

Javascript webworker won't load XML file via XMLHttpRequest

I'm am strugling to get a webworker to load an XML file from the same domain on the side of my main page, any help would be greatly appreciated.
function readXML(){
var xhr = new XMLHttpRequest(); //Only for FF
xhr.open("GET","../db/pointer.xml",true);
xhr.send(null);
xhr.onreadystatechange = function(e){
if(xhr.status == 200 && xhr.readyState == 4){
//Post back info to main page
postMessage(xhr.responseXML.getElementsByTagName("value").length);
}
}
When this runs in a script tag on the main page, i get a 3.
When running thru the WebWorker, FireBug gives me
hr.responseXML is null
postMessage(xhr.responseXML.getElementsByTagName("value").length);
In the FireBug console, GET Request responded with
<?xml version="1.0" encoding="UTF-8"?>
<root>
<value>A value</value>
<value>Another Value</value>
<value>A third Value</value>
</root>
So the response is correct but i cannot figure out where it's going wrong.
If i change responseXML to responseText the worker outputs
A value Another Value A third Value
Which is correct! why won't the script open it as an XML document?
UPDATE
function readXML(){
var xhr = new XMLHttpRequest(); //Only for FF
xhr.open("GET","../db/pointer.xml",false);
xmlhttp.setRequestHeader('Content-Type', 'text/xml');
xhr.overrideMimeType('text/xml');
xhr.send(null);
xhr.onreadystatechange = function(e){
if(xhr.status == 200 && xhr.readyState == 4){
//Post back info to main page
postMessage(xhr.responseXML.getElementsByTagName("value").length);
}
}
When setRequestHeader & overrideMimeType is changed, the onreadystatechange never fires, doesn't matter if status and readyState are there or not, it won't run. If i remove the onreadystatechange completely and just run xhr.responseXML, i get the null error again.
I still get the correct XML in as response in the console, is this a webworker issue instead of a httprequest problem? Getting desperate here :)
index.html http://www.axlonline.se/worker/index.html
worker.js http://www.axlonline.se/worker/worker.js
According to the standard, Web workers can have not have access to any type of DOM manipulation.
The DOM APIs (Node objects, Document objects, etc) are not available to workers in this version of this specification.
responseXML and channel properties are always null from an ajax request as the parsing of the XML is a DOM API. No matter the request and response headers there will be no way of getting requestXML unless you manually parse it.
Had the same Problem. Apparently XML parsing is not possible in webworkers.
I used sax.js to parse a XML on web worker.
https://github.com/isaacs/sax-js
this is basicly my parser.
function xmlParser(strict){
this.parser = sax.parser(strict, {lowercase:true});
}
xmlParser.prototype.parseFile = function(file, callback){
var _this = this;
$.ajax.get({
cache: false,
url: file,
dataType: "xml",
success: function(data){
var dom = _this.parseText(data.text);
callback( dom );
},
error: function(data){
}
});
}
xmlParser.prototype.parseText = function(xlmText){
var dom = undefined;
var activeNode = dom;
this.parser.onerror = function (e) { };
this.parser.onend = function () {};
this.parser.ontext = function (t) {
if(activeNode != undefined)
activeNode.Text = t;
};
this.parser.onopentag = function (node) {
var node = new xmlNode(node.name, activeNode, node.attributes, dom);
if(dom === undefined){
dom = node;
activeNode = node;
}else{
activeNode.Children.push(node);
activeNode = node;
}
};
this.parser.onclosetag = function (node) {
activeNode = activeNode.Parent;
};
this.parser.write(xlmText).close();
return dom;
}
xmlNode enables a jquery like handling of the tree.
function xmlFilterResult(){
this.length = 0;
}
xmlFilterResult.prototype.push = function(element){
this[this.length++] = element;
}
xmlFilterResult.prototype.attr = function(atribute){
if(this.length == 0)
return '';
return this[0].Attributes[atribute];
}
xmlFilterResult.prototype.text = function(atribute){
if(this.length == 0)
return '';
return this[0].Text;
}
xmlFilterResult.prototype.children = function(search, result){
if(result == undefined)
result = new xmlFilterResult();
if(search == undefined){
for(var i = 0; i < this.length; i++){
this[i].children(search, result);
}
}else{
this.find(search, true, result);
}
return result;
}
xmlFilterResult.prototype.find = function(search, nonrecursive, result){
if(result == undefined)
result = new xmlFilterResult();
if(search.charAt(0) == '.')
return this.findAttr('class', search.substring(1), nonrecursive, result);
else if(search.charAt(0) == '#')
return this.findAttr('id', search.substring(1), nonrecursive, result);
else
return this.findName(search, nonrecursive, result);
}
xmlFilterResult.prototype.findAttr = function(attr, value, nonrecursive, result){
if(result == undefined)
result = new xmlFilterResult();
var child;
for(var i = 0; i < this.length; i++){
child = this[i];
child.findAttr(attr, value, nonrecursive, result);
}
return result
}
xmlFilterResult.prototype.findName = function(name, nonrecursive, result){
if(result == undefined)
result = new xmlFilterResult();
var child;
for(var i = 0; i < this.length; i++){
child = this[i];
child.findName(name, nonrecursive, result);
}
return result
}
// xmlFilterResult.prototype.findID = function(id, nonrecursive){
// var child, result = new xmlFilterResult();
// for(var i = 0; i < this.length; i++){
// child = this[i];
// child.findID(id, nonrecursive, result);
// }
// return result
// }
function xmlNode(name, parent, atributes, root){
this.Name = name;
this.Children = [];
this.Parent = parent;
this.Attributes = atributes;
this.Document = root;
this.Text = '';
}
xmlNode.prototype.attr = function(atribute){
return this.Attributes[atribute];
}
xmlNode.prototype.text = function(atribute){
return this.Text;
}
xmlNode.prototype.children = function(search, result){
if(result == undefined)
result = new xmlFilterResult();
if(search == undefined){
for(i in this.Children)
result.push(this.Children[i]);
}else{
return this.find(search, true, result);
}
return result;
}
xmlNode.prototype.find = function(search, nonrecursive, result){
if(search.charAt(0) == '.')
return this.findAttr('class', search.substring(1), nonrecursive, result);
else if(search.charAt(0) == '#')
return this.findAttr('id', search.substring(1), nonrecursive, result);
else
return this.findName(search, nonrecursive, result);
}
xmlNode.prototype.findAttr = function(attr, value, nonrecursive, result){
var child, i;
if(result == undefined)
result = new xmlFilterResult();
for(i in this.Children){
child = this.Children[i];
if(child.Attributes[attr] == value)
result.push(child);
if(!nonrecursive)
child.findAttr(attr, value, nonrecursive, result);
}
return result
}
xmlNode.prototype.findName = function(name, nonrecursive, result){
var child, i;
if(result == undefined)
result = new xmlFilterResult();
for(i in this.Children){
child = this.Children[i];
if(child.Name == name){
result.push(child);
}
if(!nonrecursive)
child.findName(name, nonrecursive, result);
}
return result
}
Its nothing special but you get the idea of that to do.
You just need to set the content-type header to text/xml on the server side.
responseXML is null if the document that you're requesting isn't XML. Specifically, the content-type should be one of text/html, text/xml, application/xml, or something that ends in +xml. See the spec.
Also, see: responseXML is null and responseXML always null.
And a side note: since web workers are inherently asynchronous, you don't need to set the async flag to true in your open call.

Reading xml document in firefox

I am trying to read customers.xml using javascript.
My professor has taught us to read xml using `ActiveXObjectand he has given us an assignment to create a sample login page which checks username and password by reading customers.xml.
I am trying to use DOMParser so that it works with firefox.
But when I click on Login button I get this error.
Error: syntax error Source File:
file:///C:/Users/Searock/Desktop/home/project/project/login.html
Line: 1, Column: 1 Source Code:
customers.xml
Here's my code.
login.js
var xmlDoc = 0;
function checkUser()
{
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
//xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
/*
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.async = "false";
xmlDoc.onreadystatechange = redirectUser;
xmlDoc.load("customers.xml");
*/
var parser = new DOMParser();
xmlDoc = parser.parseFromString("customers.xml", "text/xml");
alert(xmlDoc.documentElement.nodeName);
xmlDoc.async = "false";
xmlDoc.onreadystatechange = redirectUser;
}
function redirectUser()
{
alert('');
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
var log = 0;
if(xmlDoc.readyState == 4)
{
xmlObj = xmlDoc.documentElement;
var len = xmlObj.childNodes.length;
for(i = 0; i < len; i++)
{
var nodeElement = xmlObj.childNodes[i];
var userXml = nodeElement.childNodes[0].firstChild.nodeValue;
var passXml = nodeElement.childNodes[1].firstChild.nodeValue;
var idXML = nodeElement.attributes[0].value
if(userXml == user && passXml == pass)
{
log = 1;
document.cookie = escape(idXML);
document.login.submit();
}
}
}
if(log == 0)
{
var divErr = document.getElementById('Error');
divErr.innerHTML = "<b>Login Failed</b>";
}
}
customers.xml
<?xml version="1.0" encoding="UTF-8"?>
<customers>
<customer custid="CU101">
<user>jack</user>
<pwd>PW101</pwd>
<email>jack#rediff.com</email>
</customer>
<customer custid="CU102">
<user>jill</user>
<pwd>PW102</pwd>
<email>jill#rediff.com</email>
</customer>
<customer custid="CU103">
<user>john</user>
<pwd>PW103</pwd>
<email>john#rediff.com</email>
</customer>
<customer custid="CU104">
<user>jeff</user>
<pwd>PW104</pwd>
<email>jeff#rediff.com</email>
</customer>
</customers>
I get parsererror message on line alert(xmlDoc.documentElement.nodeName);
I don't know what's wrong with my code. Can some one point me in a right direction?
Edit :
Ok, I found a solution.
var xmlDoc = 0;
var xhttp = 0;
function checkUser()
{
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
var err = "";
if(user == "" || pass == "")
{
if(user == "")
{
alert("Enter user name");
}
if(pass == "")
{
alert("Enter Password");
}
return;
}
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else // IE 5/6
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.onreadystatechange = redirectUser;
xhttp.open("GET","customers.xml",true);
xhttp.send();
}
function redirectUser()
{
var log = 2;
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
if (xhttp.readyState == 4)
{
log = 0;
xmlDoc = xhttp.responseXML;
var xmlUsers = xmlDoc.getElementsByTagName('user');
var xmlPasswords = xmlDoc.getElementsByTagName('pwd');
var userLen = xmlDoc.getElementsByTagName('customer').length;
var xmlCustomers = xmlDoc.getElementsByTagName('customer');
for (var i = 0; i < userLen; i++)
{
var xmlUser = xmlUsers[i].childNodes[0].nodeValue;
var xmlPass = xmlPasswords[i].childNodes[0].nodeValue;
var xmlId = xmlCustomers.item(i).attributes[0].nodeValue;
if(xmlUser == user && xmlPass == pass)
{
log = 1;
document.cookie = xmlId;
document.login.submit();
break;
}
}
}
if(log == 0)
{
alert("Login failed");
}
}
Thanks.
parseFromString is parsing the string "customer.xml" in your case, because the first argument needs to be a string containing the actual content of the XML document and not its name.
You can use something like this to get the xml file:
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else // IE 5/6
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET","customer.xml",false);
xhttp.send();
xmlDoc=xhttp.responseXML;
Source

Categories

Resources