construct xml string from parsed xml - javascript

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 );

Related

Can this function return DOM elements?

For some reason parsing this XML string...I'm getting this error at dom.async = false;
...in theory this should be possible?
$(document).ready( function(){
function parseXml(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("oops");
return dom;
}
});
According to Here IE11 Cannot be detected by window.ActiveXObject.

Unable to parse XML in Chrome/Opera/Safari

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;
}

create object from processor output to append/replaceChild

Attempting to add parameters to an xsl template, for use in a navigation menu.
Trying to figure out how to use the output that IXSLProcessor leaves me with.
I have the following code that works perfectly for Firefox
var xslStylesheet;
var xsltProcessor = new XSLTProcessor();
var myDOM;
var xmlDoc;
var myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "client.xsl", false);
myXMLHTTPRequest.send(null);
xslStylesheet = myXMLHTTPRequest.responseXML;
xsltProcessor.importStylesheet(xslStylesheet);
// load the xml file
myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "client.xml", false);
myXMLHTTPRequest.send(null);
xmlDoc = myXMLHTTPRequest.responseXML;
// set the parameter using the parameter passed to the outputgroup function
xsltProcessor.setParameter(null, "cid", client);
xsltProcessor.setParameter(null, "browser", "other");
var fragment = xsltProcessor.transformToFragment(xmlDoc,document);
document.getElementById("scriptHook").innerHTML = "";
document.getElementById("maincontent").replaceChild(fragment, document.getElementById("scriptHook"));
scroll(0,0);
This is the code I have (mostly pilfered from msdn)
var xslt = new ActiveXObject("Msxml2.XSLTemplate.3.0");
var xsldoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
var xslproc;
xsldoc.async = false;
xsldoc.load("client.xsl");
if (xsldoc.parseError.errorCode != 0) {
var myErr = xsldoc.parseError;
WScript.Echo("You have error " + myErr.reason);
} else {
xslt.stylesheet = xsldoc;
var xmldoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
xmldoc.async = false;
xmldoc.load("client.xml");
if (xmldoc.parseError.errorCode != 0) {
var myErr = xmldoc.parseError;
WScript.Echo("You have error " + myErr.reason);
} else {
xslproc = xslt.createProcessor();
xslproc.input = xmldoc;
xslproc.addParameter("cid", client);
xslproc.addParameter("browser", "ie");
xslproc.transform();
//somehow convert xslproc.output to object that can be used in replaceChild
document.getElementById("scriptHook").innerHTML = "";
document.getElementById("maincontent").replaceChild(xslproc.output, document.getElementById("scriptHook"));
}
}
Any and all help is appreciated, cheers.
With Mozilla you can exchange nodes between XSLT and DOM but with IE you need to take the XSLT transformation result as a string and feed that to IE's HTML parser; so for your sample I think you want
document.getElementById("scriptHook").outerHTML = xslproc.output;
which will replace the scriptHook element with the result of the transformation.

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/

NS_ERROR_FAILURE

I'm trying to implement the basic XHR listener as described on "Ashita" however, when loading firefox with the extension I recieve this error on whenever a page tries to load which prevents anything from loading: Error: uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIBinaryInputStream.readBytes]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: chrome://xhrlogger/content/overlay.js :: anonymous :: line 68" data: no]
My overlay.js is:
if (typeof Cc == "undefined") {
var Cc = Components.classes;
}
if (typeof Ci == "undefined") {
var Ci = Components.interfaces;
}
if (typeof CCIN == "undefined") {
function CCIN(cName, ifaceName){
return Cc[cName].createInstance(Ci[ifaceName]);
}
}
if (typeof CCSV == "undefined") {
function CCSV(cName, ifaceName){
if (Cc[cName])
// if fbs fails to load, the error can be _CC[cName] has no properties
return Cc[cName].getService(Ci[ifaceName]);
else
dump("CCSV fails for cName:" + cName);
};
}
var httpRequestObserver = {
observe: function(request, aTopic, aData){
if (aTopic == "http-on-examine-response") {
var newListener = new TracingListener();
request.QueryInterface(Ci.nsITraceableChannel);
newListener.originalListener = request.setNewListener(newListener);
}
},
QueryInterface: function(aIID){
if (aIID.equals(Ci.nsIObserver) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
};
function TracingListener() {
this.receivedData = []; //initialize the array
}
TracingListener.prototype =
{
originalListener: null,
receivedData: null, //will be an array for incoming data.
onDataAvailable: function(request, context, inputStream, offset, count) {
var binaryInputStream = CCIN("#mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream");
binaryInputStream.setInputStream(inputStream);
var storageStream = CCIN("#mozilla.org/storagestream;1",
"nsIStorageStream");
//8192 is the segment size in bytes, count is the maximum size of the stream in bytes
storageStream.init(8192, count, null);
var binaryOutputStream = CCIN("#mozilla.org/binaryoutputstream;1",
"nsIBinaryOutputStream");
binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));
// Copy received data as they come.
var data = binaryInputStream.readBytes(count);
this.receivedData.push(data);
binaryOutputStream.writeBytes(data, count);
//Pass it on down the chain
this.originalListener.onDataAvailable(request, context, inputStream, offset, count);
},
onStartRequest: function(request, context) {
this.originalListener.onStartRequest(request, context);
},
onStopRequest: function(request, context, statusCode) {
try
{
//QueryInterface into HttpChannel to access originalURI and requestMethod properties
request.QueryInterface(Ci.nsIHttpChannel);
var data = null;
if (request.requestMethod.toLowerCase() == "post")
{
var postText = this.readPostTextFromRequest(request, context);
if (postText)
data = ((String)(postText)).parseQuery();
}
//Combine the response into a single string
var responseSource = this.receivedData.join('');
//fix leading spaces bug
//(FM occasionally adds spaces to the beginning of their ajax responses...
//which breaks the XML)
responseSource = responseSource.replace(/^\s+(\S[\s\S]+)/, "$1");
//gets the date from the response headers on the request.
//For PirateQuesting this was preferred over the date on the user's machine
var date = Date.parse(request.getResponseHeader("Date"));
//Again a PQ specific function call, but left as an example.
//This just passes a string URL, the text of the response,
//the date, and the data in the POST request (if applicable)
/* piratequesting.ProcessRawResponse(request.originalURI.spec,
responseSource,
date,
data); */
dump(date);
dump(data);
dump(responseSource);
}
catch (e)
{
//standard function to dump a formatted version of the error to console
dump(e);
}
this.originalListener.onStopRequest(request, context, statusCode);
},
readPostTextFromRequest : function(request, context) {
try
{
var is = request.QueryInterface(Ci.nsIUploadChannel).uploadStream;
if (is)
{
var ss = is.QueryInterface(Ci.nsISeekableStream);
var prevOffset;
if (ss)
{
prevOffset = ss.tell();
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
}
// Read data from the stream..
var charset = "UTF-8";
var text = this.readFromStream(is, charset, true);
if (ss && prevOffset == 0)
ss.seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
return text;
}
else {
dump("Failed to Query Interface for upload stream.\n");
}
}
catch(exc)
{
dump(exc);
}
return null;
},
QueryInterface: function (aIID) {
if (aIID.equals(Ci.nsIStreamListener) ||
aIID.equals(Ci.nsISupports)) {
return this;
}
throw Components.results.NS_NOINTERFACE;
},
readFromStream : function(stream, charset, noClose) {
var sis = CCSV("#mozilla.org/binaryinputstream;1",
"nsIBinaryInputStream");
sis.setInputStream(stream);
var segments = [];
for (var count = stream.available(); count; count = stream.available())
segments.push(sis.readBytes(count));
if (!noClose)
sis.close();
var text = segments.join("");
return text;
}
}
var observerService = Cc["#mozilla.org/observer-service;1"]
.getService(Ci.nsIObserverService);
observerService.addObserver(httpRequestObserver,
"http-on-examine-response", false);
dump("WTFBBQ");
Any help would be most appreciated.
Mine seems to work fine with less code. Try replacing your onDataAvailable function code with:
var binaryInputStream = Components.classes["#mozilla.org/binaryinputstream;1"].createInstance(Components.interfaces.nsIBinaryInputStream);
binaryInputStream.setInputStream(inputStream);
this.receivedData.push(binaryInputStream.readBytes(count));

Categories

Resources