XML in html div? - javascript

I have put some xml-fragments in a div and retrieve it with getElementsByTagName. It works fine in Firefox but Internet Explorer ain't so nice... What should I do to fix this?
var thumbnails = content.getElementsByTagName("thumbnails");
for (var i = 0; i < thumbnails.length; i++) {
thumbnails[i].innerHTML

You can't put arbitrary XML in an HTML document, in general. It's invalid HTML, and browser parsers may try to ‘fix’ the broken HTML, mangling your data.
You can embed XML inside HTML using <xml> data islands in IE, or using native-XHTML with custom namespaces in other browsers. But apart from the compatibility issue of the two different methods, it's just not really a very good idea.
Further, even if it worked, plain XML Element nodes don't have an innerHTML property in any case.
You could embed XML inside JavaScript:
<script type="text/javascript">
var xml= '<nails><thumb id="foo">bar</thumb><thumb id="bof">zot</thumb></nails>';
var doc= parseXML(xml);
var nails= doc.getElementsByTagName('thumb');
for (var i = 0; i<nails.length; i++) {
alert(nails[i].getAttribute('id'));
}
function parseXML(s) {
if ('DOMParser' in window) {
return new DOMParser().parseFromString(s, 'text/xml');
} else if ('ActiveXObject' in window) {
var doc= new ActiveXObject('MSXML2.DOMDocument');
doc.async= false;
doc.loadXML(s);
return doc;
} else {
alert('Browser cannot parse XML');
}
}
</script>
But this means you have to encode the XML as a JavaScript string literal (eg. using a JSON encoder if you are doing it dynamically). Alternatively you could use an XMLHttpRequest to fetch a standalone XML document from the server: this is more widely supported than the DOMParser/ActiveX approach.
If you are just using XML to pass data to your script, you will find it a lot easier to write JavaScript literals to do it instead of mucking about with parsing XML.
<script type="text/javascript">
var nails= [
{"id": "foo", "text": "bar"},
{"id": "bof", "text": "zot"}
];
for (var i = 0; i<nails.length; i++) {
// do something
}
</script>
Again, you can produce this kind of data structure easily using a JSON encoder if you need to do it dynamically.

IE 7 has a security issue with the innerHTML property of a DOM element. This security check silently blocks some code. It appears this may be your problem. I do not know if this is an issue with IE 8.
The fix just add the dynamically created element in the DOM tree before accessing any of the properties, not after.
However, for best practices it is wise to change the way you are doing this. Perhaps you should edit your question to ask a better way to do this.

What I've found to be the best way of doing this is to put your xml into a textarea. This is also ext-js's suggestion. That way, the browser doesn't try to create html out of your xml. When you retrieve its value, you just retrieve the texarea's value.
However, as other people have mentioned, I would suggest you retrieve the xml from the server for better separation between html and data, unless you really need to keep your http requests to a minimum.

Related

How Edit data of an XML node with Javascript

I want to write some data in an existing local XML file with Javascript with some text from an Html page. Is it possible to change content of nodes?
Here is XML sample:
<Notepad>
<Name>Player1</Name>
<Notes>text1</Notes>
</Notepad>
I will get some more text from input and want to add it after "text1", but can't find a solution.
function SaveNotes(content,player)
{
var xml = "serialize.xml";
var xmlTree = parseXml("<Notepad></Notepad>");
var str = xmlTree.createElement("Notes");
$(xmlTree).find("Notepad").find(player).append(str);
$(xmlTree).find("Notes").find(player).append(content);
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
}
Here is the code to manipulate xml content or xml file :
[Update]
Please check this Fiddle
var parseXml;
parseXml = function(xmlStr) {
return (new window.DOMParser()).parseFromString(xmlStr, "text/xml");
};
var xmlTree = parseXml("<root></root>");
function add_children(child_name, parent_name) {
str = xmlTree.createElement(child_name);
//strXML = parseXml(str);
$(xmlTree).find(parent_name).append(str);
$(xmlTree).find(child_name).append("hello");
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
alert(xmlString);
}
add_children("apple", "root");
add_children("orange", "root");
add_children("lychee", "root");
you can use it for searching in xml as well as adding new nodes with content in it. (And sorry i dont know how to load xml from client side and display it.)
but this fiddle demo will be helpful in adding content in xml and searching in it.
Hope it helps :)
If you want to achieve this on the client side you can parse your xml into a document object:
See
https://developer.mozilla.org/en-US/docs/Web/Guide/Parsing_and_serializing_XML
and
http://www.w3schools.com/xml/tryit.asp?filename=tryxml_parsertest2
And then manipulate it like you would the DOM of any html doc, e.g. createElement, appendChild etc.
See https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
Then to serialize it into a String again you could use https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
Persisting the data
Writing to a local file is not possible in a cross-browser way. In IE you could use ActiveX to read/write file.
You could use cookies to store data on the client side, if your data keeps small enough.
In HTML5 you could use local storage, see http://www.w3schools.com/html/html5_webstorage.asp
Try to use these two package one to convert to json and when is finish the other to come back
https://www.npmjs.com/package/xml2json
https://www.npmjs.com/package/js2xmlparser

Multiple HTML DOMs - Parse and Transfer Data

I am requesting full HTML5 documents via Ajax using jQuery. I want to be able to parse them and transfer elements to my main page DOM, ideally with all major browsers, including mobile. I don't want to create an iframe as I want the process to be as quick as possible. With Chrome & Firefox I can do the following:
var contents = $(document.createElement('html'));
contents[0].innerHTML = data; // data : HTML document string
This will create a proper document, somewhat surprisingly, just without a doctype. In IE9, however, one may not use the innerHTML to set the contents of the html element. I tried to do the following, without any luck:
Create a DOM, open it, write to it and close it. Issue: on doc.open, IE9 throws an exception called Unspecified error..
var doc = document.implementation.createHTMLDocument('');
doc.open();
doc.write(data);
doc.close();
Create an ActiveX DOM. This time, the result is better but upon transferring / copying elements between documents IE9 crashes. Bad because no IE8 support (adoptNode / importNode support).
var doc = new ActiveXObject('htmlfile');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
document.adoptNode(contents);
I was thinking about recursively recreating the elements, instead of transferring them between my documents, but that seems like an expensive task, given that I can have a lot nodes to transfer. I like my last ActiveX example as that will most likely work in IE8 and earlier (for parsing, at least).
Any ideas on this? Again, not only I need to be able to parse the head and body, but I also need to be able to append these new elements to my main dom.
Thanks much!
Answering my own question... To solve my issue I used all solutions mentioned in my post, with try/catch blocks if a browser throws an error (oh, how we love thee IE!). The following works in IE8, IE9, Chrome 23, Firefox 17, iOS 4 and 5, Android 3 & 4. I have not tested Android 2.1-2.3 and IE7.
var contents = $('');
try {
contents = $(document.createElement('html'));
contents[0].innerHTML = data;
}
catch(e) {
try {
var doc = document.implementation.createHTMLDocument('');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
}
catch(e) {
var doc = new ActiveXObject('htmlfile');
doc.open();
doc.write(data);
doc.close();
contents = $(doc.documentElement);
}
}
At this point we can find elements using jQuery. Transferring them to a different DOM creates a bit of a problem. There are a couple of methods that do this, but they are not widely supported yet (importNode & adoptNode) and/or are buggy. Given that our selector string is called 'selector', below I re-created the found elements and append them to '.someDiv'.
var fnd = contents.find(selector);
if(fnd.length) {
var newSelection = $('');
fnd.each(function() {
var n = document.createElement(this.tagName);
var attr = $(this).prop('attributes');
n.innerHTML = this.innerHTML;
$.each(attr,function() { $(n).attr(this.name, this.value); });
newSelection.push(n);
});
$('.someDiv').append(newSelection);
};

How to add additional xmlns namespace attributes to XML in IE via javascript

I'm a little bit stuck trying to attach multiple namespaces to an XML element via javascript across browsers; I've tried about a dozen different ways to no avail.
I usually use plain old javascript but for the sake of keeping this example short, this is how what I'm doing would be done via jQuery:
var soapEnvelope = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"></soapenv:Envelope>';
var jXML = jQuery.parseXML(soapEnvelope);
$(jXML.documentElement).attr("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
In both Chrome and FF, this works as expected giving a result like this:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
But in IE9, I get a result like this:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:NS1="" NS1:xmlns:xsd="http://www.w3.org/2001/XMLSchema"/>
And I cannot find a way to add this namespace attribute without IE9 adding this NS1 prefix to my namespaces. Also if I try passing this result back into $.parseXML(result) I get a malformed XML exception.
Am I misunderstanding something to do with the way namespaces are declared in IE or can anyone suggest a way I can get a consistent result across browsers?
Thanks in advance
In case anyone else runs into a similar problem to this, I ended up finding out that it can be fixed by initialising the IE XML DOM object differently to the way jQuery does it. I used something similar to the following and now the xml namespaces seem to be working fine across all major browsers and the jQuery attr method will now work again also.
var getIEXMLDOM = function() {
var progIDs = [ 'Msxml2.DOMDocument.6.0', 'Msxml2.DOMDocument.3.0' ];
for (var i = 0; i < progIDs.length; i++) {
try {
var xmlDOM = new ActiveXObject(progIDs[i]);
return xmlDOM;
} catch (ex) { }
}
return null;
}
var xmlDOM;
if ( $.browser.msie ) {
xmlDOM = getIEXMLDOM();
xmlDOM.loadXML(soapEnvelope);
} else {
xmlDOM = jQuery.parseXML(soapEnvelope);
}
$(xmlDOM.documentElement).attr("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");

How to get hyperlink ids in another html file

am doing a project it requires a web site.on this site i have to darw state diagram for hyperlinks.that is how the hyperlinks are attached to one another on a site.am using html.how to get hyperlink id in another html file.i know about document.getElementById.
Thanks inadvance
That would require a way to access another HTML file through AJAX, which is not possible if it isn't on your domain or if CORS isn't enabled.
There's however quite a few things you could do:
Use your own server-side as proxy for fetching the HTML file.
Do the processing on the server-side and let JavaScript plot the data.
Do everything on the server-side.
If you'd like to get the ID's of a link you should use a HTML parser. Modern browsers include a such, it's called DOMParser. You'd do something like this:
var parser = new DOMParser();
var doc = parser.parseFromString(yourHTMLSource, 'text/html');
var links = doc.getElementsByTagName('a');
for(var i = 0, length = links.length; i < length; i++) {
links[i].getAttribute('id'); // -> Returns the ID of the link, if any
}
As I remember it, IE doesn't support this, but has it's own module for HTML parsing with some different methods, but still relatively easy to use.

Simplest possible method: html break in XML doc

I have a c program which outputs a number of lines to another c program which stuffs them in a PHP page which is loaded with AJAX. The problem is that the output is a number of lines, which is fine to look at, but which, when viewed as HTML, lack line breaks.
The initial thought I had was obviously to put line breaks in with the output. -- That worked fine, especially since I was using responseText to handle the AJAX output. Now I have discovered that along with the raw text, a bit of metadata also needs to be part of the AJAX response. I jumped over to using responseXML, only to find that the tags no longer worked correctly. At this point I could slog through any number of tutorials to figure out how to work some more complicated mechanism, but I really just want a hack. Could I embed the metadata in an html comment and use the DOM to dig it out (I looked and don't see a good method to get to comments using the dom...)? Could I use the xml directly as html somehow? Could I use CDATA in the xml document(this doesn't seem hopeful)? Could I just use newlines until the code reaches the webpage and then have JS insert the br tags?
I don't need any other formatting, just line breaks, and all this needs to do is work, the less complex the better.
How about using a XSLT stylesheet to format your incoming XML. Save the following as an .html file for an example. Sources : http://www.w3schools.com/xsl/xsl_client.asp & http://www.w3schools.com/dom/dom_parser.asp
<html>
<head>
<script>
//YOUR XML FROM AJAX
var XML = "<top><meta><itemone>test meta</itemone></meta><rows><row>line one</row><row>line two</row><row>line three</row></rows></top>";
//A stylesheet to format the lines that come back.
var XSLT = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"><xsl:template match="/"><h2>Lines</h2><xsl:for-each select="descendant::row"><xsl:value-of select="self::*"/><br /></xsl:for-each></xsl:template></xsl:stylesheet>'
function loadXMLDoc(xml)
{
var tempXML;
//IE
if (window.ActiveXObject)
{
tempXML=new ActiveXObject("Microsoft.XMLDOM");
tempXML.loadXML(xml);
}
else if(window.DOMParser)
{
parser=new DOMParser();
tempXML=parser.parseFromString(xml,"text/xml");
}
return tempXML;
}
function displayResult()
{
var xmlDoc = loadXMLDoc(XML);
var xsltDoc = loadXMLDoc(XSLT);
// code for IE
if (window.ActiveXObject)
{
var ex=xmlDoc.transformNode(xsltDoc);
document.getElementById("example").innerHTML=ex;
}
// code for Mozilla, Firefox, Opera, etc.
else if (document.implementation && document.implementation.createDocument)
{
var xsltProcessor=new XSLTProcessor();
xsltProcessor.importStylesheet(xsltDoc);
var resultDocument = xsltProcessor.transformToFragment(xmlDoc,document);
document.getElementById("example").appendChild(resultDocument);
}
}
</script>
</head>
<body onload="displayResult()">
<div id="example" />
</body>
</html>
Thanks for all the good suggestions, but I eventually decided to just prepend a fixed number of descriptor bytes to each text response and then use the substring command to get either the descriptor bytes or the main text response.
This allows me to keep using the simpler response-text mechanism, and is otherwise uncomplicated.
I would have used custom headers but I realized that that would have required buffering the whole output in yet ANOTHER place since the php script actually only contains a single system() call, and has no idea what the C program behind it is doing.

Categories

Resources