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/
Related
So I'm studying for an exam and I only have a quick question that has been buggin me for a while. I use AJAX to obtain a XML file to parse it and insert its values into a select element. This is the code:
<html>
<head>
</head>
<body>
<button onclick="EnviaPedido()">Submeter</button>
<select id="select"></select>
<script type="text/javascript">
var xmlHttpObj;
function CreateXmlHttpRequestObject() {
if (window.XMLHttpRequest) {
xmlHttpObj = new XMLHttpRequest()
}
else if (window.ActiveXObject) {
xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP")
}
return xmlHttpObj;
}
function EnviaPedido() {
xmlHttpObj = CreateXmlHttpRequestObject();
xmlHttpObj.open("POST", "agenda.xml", true);
xmlHttpObj.onreadystatechange = ProcessaReposta;
xmlHttpObj.send();
}
function ProcessaReposta() {
if (xmlHttpObj.readyState == 4 && xmlHttpObj.status == 200) {
var response = xmlHttpObj.responseText;
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(response, "text/xml");
} else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(response);
}
var select = document.getElementById("select");
var centrosInvestigacao = xmlDoc.getElementsByTagName("centro_de_investigacao");
for(i = 0; i < centrosInvestigacao.length; i++) {
var option = document.createElement("option");
option.innerHTML = centrosInvestigacao[i].childNodes[1].textContent;
select.appendChild(option);
}
}
}
</script>
<body>
</html>
And this is the XML that is returned:
<FCT>
<centro_de_investigacao id="1">
<nome>GECAD</nome>
<local>ISEP</local>
<classificao>Muito bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="2">
<nome>DEF</nome>
<local>ISEP</local>
<classificao>Bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="3">
<nome>ABC</nome>
<local>FEUP</local>
<classificao>Muito mau</classificao>
</centro_de_investigacao>
</FCT>
So when I want to obtain the 'nome' field why do I have to use
option.innerHTML = centrosInvestigacao[i].childNodes[1].textContent;
instead of
option.innerHTML = centrosInvestigacao[i].childNodes[0].textContent;
I know it's probably a stupid question but it's starting to piss me off not knowing if this is the expected behaviour or if I'm somehow screwing this up.
Thanks.
I made a small snipset of the problem that also shows part of the answer. I would think that the encoding of the XML document you are parsing is "off", in that sence that the first element of your childNodes, is actually a textnode between the last quote of centro_de_investigacao> and the start tag of <nome.
If you check the snipset (you can play around with the index parameter for example), you would see that the first button doesn't need the index increase to 1, but can work as expected with the first element, nl the one at index 0.
So remove the whitespaces from your XML document, and you should be fine.
Whitespaces: tab, space, newline
// mocked, no real data
var xmlHttpObj;
function CreateXmlHttpRequestObject() {
function Mock() {
this.callready = function() {
this.readyState = 4;
this.status = 200;
this.statusMsg = "OK";
if (this.onreadystatechange && this.onreadystatechange.call) {
setTimeout(this.onreadystatechange.bind(this), 0);
}
};
this.open = function(methodType, url, async) {
var el = document.getElementById('dataXml-' + url.split('.')[0]),
content = el ? el.innerHTML : '';
if (typeof async === 'undefined' || async) {
// no action till send is executed
this.responseText = content;
this.responseXml = content;
return;
}
return content;
};
this.send = function(data) {
this.callready();
};
}
return new Mock();
}
function EnviaPedido(index, url) {
xmlHttpObj = CreateXmlHttpRequestObject();
xmlHttpObj.open("POST", url, true);
xmlHttpObj.onreadystatechange = ProcessaReposta.bind(this, index);
xmlHttpObj.send();
}
function ProcessaReposta(index, url) {
if (xmlHttpObj.readyState == 4 && xmlHttpObj.status == 200) {
var response = xmlHttpObj.responseText;
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(response, "text/xml");
} else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(response);
}
var select = document.getElementById("select");
var centrosInvestigacao = xmlDoc.getElementsByTagName("centro_de_investigacao");
select.options = [];
for (i = 0; i < centrosInvestigacao.length; i++) {
var option = new Option();
var item = centrosInvestigacao[i].childNodes[index];
option.text = item.textContent;
select.options[i] = option;
}
}
}
<template id="dataXml-agenda"><FCT><centro_de_investigacao id="1"><nome>GECAD</nome><local>ISEP</local><classificao>Muito bom</classificao></centro_de_investigacao><centro_de_investigacao id="2"><nome>DEF</nome><local>ISEP</local><classificao>Bom</classificao></centro_de_investigacao><centro_de_investigacao id="3"><nome>ABC</nome><local>FEUP</local><classificao>Muito mau</classificao></centro_de_investigacao></FCT></template>
<template id="dataXml-original-agenda"><FCT>
<centro_de_investigacao id="1">
<nome>GECAD</nome>
<local>ISEP</local>
<classificao>Muito bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="2">
<nome>DEF</nome>
<local>ISEP</local>
<classificao>Bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="3">
<nome>ABC</nome>
<local>FEUP</local>
<classificao>Muito mau</classificao>
</centro_de_investigacao>
</FCT></template>
<select id="select"></select>
<button id="btnGenerate" type="button" onclick="EnviaPedido(0, 'agenda.xml');">Get info</button>
<button id="btnGenerate" type="button" onclick="EnviaPedido(1, 'original-agenda.xml');">Get info false contentType</button>
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.
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;
}
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.
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 );