I'm using jQuery's XML parser on some simple content that contains HTML.
Extracting the full HTML text using jQuery's .html() or standard javascript .innerHTML works fine in Chrome, but not in Internet Explorer 9. jQuery's .text() works in both cases, but I need the html tags extracted as well.
How can I make it work with IE9 as well?
You can test it out here:
http://jsfiddle.net/199vLsgz/
XML:
<script id="xml_data" type="text/xml">
<model_data name="The model ">
<person_responsible></person_responsible>
<objects>
<object name="Available B reports" id="obj1" >
<description>this is a description <br/> oh look, another line!</description>
</object>
</objects>
</model_data>
</script>
Code:
$(function() {
var xml = $("#xml_data").text();
var xmlDoc = $.parseXML(xml);
$xml = $(xmlDoc);
var desc = $xml.find("model_data > objects > object[id='obj1'] > description");
alert(desc.html());
})
Xml elements do not have innerHTML defined inside IE which is what's being used with the html function of jquery.
Firstly you need to use CDATA to preserve tags inside xml tags
<description><![CDATA[this is a description <br/> oh look, another line!]]></description>
then you can try to use the textContent property:
alert(desc[0].textContent); //desc.text() will also work now
And you also can add the content correctly using something like:
$('#some-container').html(desc[0].textContent);
$(function() {
var xml = $("#xml_data").text();
var xmlDoc = $.parseXML(xml);
$xml = $(xmlDoc);
console.log($xml)
var desc = $xml.find("model_data > objects > object[id='obj1'] > description");
alert(desc[0].textContent);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script id="xml_data" type="text/xml">
<model_data name="The model">
<person_responsible></person_responsible>
<objects>
<object name="Available B reports" id="obj1" >
<description><![CDATA[this is a description <br/> oh look, another line!]]></description>
</object>
</objects>
</model_data>
</script>
Related
I have a string containing content in some html tags and also some text alone.
It looks like this :
var str = "<p></p><p><i>blabla</i></p><p><i><b>blaaaaaablaaaaa</b></i></p><iframe src="..." height="111" width="333"></iframe><p></p><p><sub>hello blabla</sub></p><p><br></p><iframe src="..." height="444" width="888"></iframe>"
I would like to extract somehow in Javascript or AngularJS only some tag (including content and attributes) then put them into an array.
For example, if I want only <iframe> tag, I should have this :
var array = ["<iframe src='...' height='111' width='333'></iframe>", "<iframe src='...' height='444' width='888'></iframe>"];
If I want <p> tag then :
var array = ["", "<i>blabla</i>","<i><b>blaaaaaablaaaaa</b></i>","","<sub>hello blabla</sub>","<br>"];
Any suggestion ? Thanks !
NOTE : Don't give an answer using Jquery please !
You could create an angular element and get the text out of it.
Example:
$scope.array =[];
$scope.eles=
angular.element(str).find('iframe');
[].forEach.call($scope.eles, function (ctl) {
$scope.name.push(angular.element(ctl).text())
});
here is a demo: http://jsfiddle.net/Lvc0u55v/5122/
Edit
To get all the html of the tag you can do:
angular.element(str).find('iframe');
[].forEach.call($scope.eles, function (ctl) {
$scope.name.push(ctl.outerHTML)
});
demo: http://jsfiddle.net/Lvc0u55v/5123/
try this code:
var iFrameArr= str.match("<iframe>(.*)<iframe>");
var iFrameContent = iFrameArr[1];
You will want to look at splitting up the string with regex using a filter such as '(<iframe>).*(<\/iframe>)'. This will find the tags of and as well as everything in between, putting it into a capture group per iteration found.
Set the html content to the DOM and extract the iframe tag using jquery
Assuming you have a div with id='test' in your DOM
var str = "<div> .... </div> <iframe src=".....">..</iframe>
text blabla
<iframe src="....."> ....blabla2.... </iframe>
....
<p>.....</p>
......";
$('#test').html(str);
var ar=[]
$('#test iframe').each(function() {
var x = $(this).wrap('<p/>').parent().html();//wrap the iframe with element p and get the html of the parent
ar.push(x)//add the html content to array
});
//now ar contains the expected output
I have tried to retrieve the top level 'label' attribute from the following xml using jquery, and having parsed it into a DOM object with no luck. Any suggestions on how I can do this ? I've tried using children(),parent() functions with no luck - I get either no result, or end up having all instances of the label tags passed back to me.
jquery:
xml = $.parseXML(xmlString);
$xml = $(xml);
I traverse fields via $($xml).find('fields').each(function(){ etc...
but cannot get that top level label data!
<customobject>
<label>want this content</label>
<fields>
<label>foo</label>
<attr1></attr1>
<attr2></attr2>
</fields>
<fields>
<label>foo2</label>
<attr1></attr1>
<attr2></attr2>
</fields>
</customobject>
You can look for label which is a child of customobject like below. Just using find('label') will return contents from all the label elements
var xmlString = '<customobject><label>want this content</label><fields><label>foo</label><attr1></attr1><attr2></attr2></fields><fields><label>foo2</label><attr1></attr1><attr2></attr2></fields></customobject>';
var xml = $.parseXML(xmlString);
var $xml = $(xml);
alert($xml.find('customobject > label').text())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Hope this will be helpful
var xml = "<customobject>"+
"<label>want this content</label>"+
"<fields>"+
"<label>foo</label>"+
"<attr1></attr1>"+
"<attr2></attr2>"+
"</fields>"+
"<fields>"+
"<label>foo2</label>"+
"<attr1></attr1>"+
"<attr2></attr2>"+
"</fields>"+
"</customobject>";
xmlDoc = $.parseXML(xml ),
$xml = $( xmlDoc ),
$firstLabelbject = $xml.find( "customobject label")[0].innerHTML; // Will select first label
console.log($firstLabelbject);
JSFIDDLE EXAMPLE
Is it possible to create an XML file with some data in JavaScript? I have the data stored in variables.
I've googled around a bit and it doesn't seem like it's talked about much. I thought I could use XMLWriter such as this:
var XML = new XMLWriter();
XML.BeginNode ("testing");
XML.Node("testingOne");
XML.Node("TestingTwo");
XML.Node("TestingThree");
XML.EndNode();
as stated in this tutorial: EHow Tutorial
However, when I execute this code, I get the following error:
ReferenceError: XMLWriter is not defined
How can I solve this error?
Disclaimer: The following answer assumes that you are using the JavaScript environment of a web browser.
JavaScript handles XML with 'XML DOM objects'.
You can obtain such an object in three ways:
1. Creating a new XML DOM object
var xmlDoc = document.implementation.createDocument(null, "books");
The first argument can contain the namespace URI of the document to be created, if the document belongs to one.
Source: https://developer.mozilla.org/en-US/docs/Web/API/DOMImplementation/createDocument
2. Fetching an XML file with XMLHttpRequest
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
var xmlDoc = xhttp.responseXML; //important to use responseXML here
}
xhttp.open("GET", "books.xml", true);
xhttp.send();
3. Parsing a string containing serialized XML
var xmlString = "<root></root>";
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xmlString, "text/xml"); //important to use "text/xml"
When you have obtained an XML DOM object, you can use methods to manipulate it like
var node = xmlDoc.createElement("heyHo");
var elements = xmlDoc.getElementsByTagName("root");
elements[0].appendChild(node);
For a full reference, see http://www.w3schools.com/xml/dom_intro.asp
Note:
It is important, that you don't use the methods provided by the document namespace, i. e.
var node = document.createElement("Item");
This will create HTML nodes instead of XML nodes and will result in a node with lower-case tag names. XML tag names are case-sensitive in contrast to HTML tag names.
You can serialize XML DOM objects like this:
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(xmlDoc);
Consider that we need to create the following XML document:
<?xml version="1.0"?>
<people>
<person first-name="eric" middle-initial="H" last-name="jung">
<address street="321 south st" city="denver" state="co" country="usa"/>
<address street="123 main st" city="arlington" state="ma" country="usa"/>
</person>
<person first-name="jed" last-name="brown">
<address street="321 north st" city="atlanta" state="ga" country="usa"/>
<address street="123 west st" city="seattle" state="wa" country="usa"/>
<address street="321 south avenue" city="denver" state="co" country="usa"/>
</person>
</people>
we can write the following code to generate the above XML
var doc = document.implementation.createDocument("", "", null);
var peopleElem = doc.createElement("people");
var personElem1 = doc.createElement("person");
personElem1.setAttribute("first-name", "eric");
personElem1.setAttribute("middle-initial", "h");
personElem1.setAttribute("last-name", "jung");
var addressElem1 = doc.createElement("address");
addressElem1.setAttribute("street", "321 south st");
addressElem1.setAttribute("city", "denver");
addressElem1.setAttribute("state", "co");
addressElem1.setAttribute("country", "usa");
personElem1.appendChild(addressElem1);
var addressElem2 = doc.createElement("address");
addressElem2.setAttribute("street", "123 main st");
addressElem2.setAttribute("city", "arlington");
addressElem2.setAttribute("state", "ma");
addressElem2.setAttribute("country", "usa");
personElem1.appendChild(addressElem2);
var personElem2 = doc.createElement("person");
personElem2.setAttribute("first-name", "jed");
personElem2.setAttribute("last-name", "brown");
var addressElem3 = doc.createElement("address");
addressElem3.setAttribute("street", "321 north st");
addressElem3.setAttribute("city", "atlanta");
addressElem3.setAttribute("state", "ga");
addressElem3.setAttribute("country", "usa");
personElem2.appendChild(addressElem3);
var addressElem4 = doc.createElement("address");
addressElem4.setAttribute("street", "123 west st");
addressElem4.setAttribute("city", "seattle");
addressElem4.setAttribute("state", "wa");
addressElem4.setAttribute("country", "usa");
personElem2.appendChild(addressElem4);
var addressElem5 = doc.createElement("address");
addressElem5.setAttribute("street", "321 south avenue");
addressElem5.setAttribute("city", "denver");
addressElem5.setAttribute("state", "co");
addressElem5.setAttribute("country", "usa");
personElem2.appendChild(addressElem5);
peopleElem.appendChild(personElem1);
peopleElem.appendChild(personElem2);
doc.appendChild(peopleElem);
If any text need to be written between a tag we can use innerHTML property to achieve it.
Example
elem = doc.createElement("Gender")
elem.innerHTML = "Male"
parent_elem.appendChild(elem)
For more details please follow the below link. The above example has been explained there in more details.
https://developer.mozilla.org/en-US/docs/Web/API/Document_object_model/How_to_create_a_DOM_tree
xml-writer(npm package)
I think this is the good way to create and write xml file easy.
Also it can be used on server side with nodejs.
var XMLWriter = require('xml-writer');
xw = new XMLWriter;
xw.startDocument();
xw.startElement('root');
xw.writeAttribute('foo', 'value');
xw.text('Some content');
xw.endDocument();
console.log(xw.toString());
Simply use
var xmlString = '<?xml version="1.0" ?><root />';
var xml = jQuery.parseXML(xml);
It's jQuery.parseXML, so no need to worry about cross-browser tricks. Use jQuery as like HTML, it's using the native XML engine.
this work for me..
var xml = parser.parseFromString('<?xml version="1.0" encoding="utf-8"?><root></root>', "application/xml");
developer.mozilla.org/en-US/docs/Web/API/DOMParser
Only works in IE
$(function(){
var xml = '<?xml version="1.0"?><foo><bar>bar</bar></foo>';
var xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(xml);
alert(xmlDoc.xml);
});
Then push xmlDoc.xml to your java code.
Your code is referencing this library
You can include it, and then your code in question should run as is. If you want to do this without prepending the library & build it with builtin functions only - follow answer from #Seb3736.
In Browser Example
<html>
<head>
<script src="Global.js" language="javascript"></script>
<script src="XMLWriter.js" language="javascript"></script>
<script language="javascript" type="text/javascript">
function genXML(){
var XML = new XMLWriter();
XML.BeginNode ("testing");
XML.Node("testingOne");
XML.Node("TestingTwo");
XML.Node("TestingThree");
XML.EndNode();
//Do something... eg.
console.log(XML.ToString); //Yes ToString() not toString()
}
</script>
</head>
<body>
<input type="submit" value="genXML" onclick="genXML();">
</body>
</html>
I am using a way to insert some javascript code in the page which works with all browsers but not with IE. Here is a sample:
http://boxfly.free.fr/tmp/innerjs.html
The line which does not work properly with IE is:
ele.text = document.getElementById('DIV_js').innerHTML ;
If I change this line to:
ele.text = 'alert("Hello")' ;
It works. But I need to be able to insert code which is on a lot of lines, not only one line for displaying an alert, that's why I am using a DIV to contain the Javascript code... ;)
Does anyone know how to make this script work with IE:
<body>
<div id="DIV_js" style="display:none;">
var i = 'here' ;
function hello() {
alert('toto says ' + i) ;
}
</div>
<script>
var ele = document.createElement("script") ;
ele.type = 'text/javascript' ;
ele.text = document.getElementById('DIV_js').innerHTML ;
document.body.insertBefore(ele, (document.getElementsByTagName("div"))[0]);
</script>
<span onClick="hello();">Click to display alert</span>
</body>
See if this works in IE: http://jsfiddle.net/nGxTf/
I changed it to an eval() call, rather than inserting it into a script element.
Try this:
// The rest of the code above omitted for brievity
var ele = document.createElement("script");
ele.type = 'text/javascript';
ele.innerHTML = document.getElementById('DIV_js').innerHTML;
// Don't use getElementsByTagName, you risk inserting the script in more than one div
document.getElementById('yourDiv').appendChild(ele);
innerHTML works form IE6 to IE9 but it has buggy.innerHTML on tbody elements is readOnly in IE
I have an HTML page which contains an Object tag to host an embedded HTML page.
<object style="border: none;" standby="loading" id="contentarea"
width="100%" height="53%" type="text/html" data="test1.html"></object>
However, I need to be to change the HTML page within the object tag. The current code seems to create a clone of the object and replaces the existing object with it, like so:
function changeObjectUrl(newUrl)
{
var oContentArea = document.getElementById("contentarea");
var oClone = oContentArea.cloneNode(true);
oClone.data = newUrl;
var oPlaceHolder = document.getElementById("contentholder");
oPlaceHolder.removeChild(oContentArea);
oPlaceHolder.appendChild(oClone);
}
This seems a rather poor way of doing this. Does anyone know the 'correct' way of changing the embedded page?
Thanks!
EDIT: In response to answers below, here is the full source for the page I am now using. Using the setAttribute does not seem to change the content of the Object tag.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Test</title>
<script language="JavaScript">
function doPage()
{
var objTag = document.getElementById("contentarea");
if (objTag != null)
{
objTag.setAttribute('data', 'Test2.html');
alert('Page should have been changed');
}
}
</script>
</head>
<body>
<form name="Form1" method="POST">
<p><input type="button" value="Click to change page" onclick="doPage();" /></p>
<object style="visibility: visible; border: none;" standby="loading data" id="contentarea" title="loading" width="100%" height="53%" type="text/html" data="test1.html"></object>
</form>
</body>
</html>
The Test1.html and Test2.html pages are just simple HTML pages displaying the text 'Test1' and 'Test2' respectively.
You can do it with setAttribute
document.getElementById("contentarea").setAttribute('data', 'newPage.html');
EDIT:
It is also recommended that you use the window.onload to ensure that the DOM has loaded, otherwise you will not be able to access objects within it.
It could be something like this:
function changeData(newURL) {
if(!document.getElementById("contentarea"))
return false;
document.getElementById("contentarea").setAttribute('data', newURL);
}
window.onload = changeData;
You can read more about window.onload here
This seems to be a browser bug, setAttribute() should work. I found this workaround, which seems to work in all browsers:
var newUrl = 'http://example.com';
var objectEl = document.getElementById('contentarea');
objectEl.outerHTML = objectEl.outerHTML.replace(/data="(.+?)"/, 'data="' + newUrl + '"');
The above solutions did not work properly in Firefox, the Object tag doesn't refresh for some reason. My object tags show SVG images.
My working solution for this was to replace the complete Object node with a clone:
var object = document.getElementById(objectID);
object.setAttribute('data', newData);
var clone = object.cloneNode(true);
var parent = object.parentNode;
parent.removeChild(object );
parent.appendChild(clone );
Here's how I finally achieved it. You can do
document.getElementById("contentarea").object.location.href = url;
or maybe
document.getElementById("contentarea").object.parentWindow.navigate(url);
The Object element also has a 'readyState' property which can be used to check whether the contained page is 'loading' or 'complete'.
I found a very simple solution that also works in Chrome. The trick is to make the object (or a parent element) invisible, change the data attribute, and then make the object visible again.
In the code below, it is assumed that object_element is the object element and parent_element is the parent, and url is the url of the data.
parent_element.style.display = 'none'; // workaround for Chrome
object_element.setAttribute('data', url);
parent_element.style.display = '';
Following user2802253, I use this one on Safari and Firefox, which also forces a redraw. (sorry, not enough reputation to post as a simple comment).
theObject.style.visibility = null;
theObject.setAttribute("data", url);
theObject.style.visibility = "visible";
var obj = document.getElementById("pdfDoc");
obj.setAttribute('data', newPdf);
worked on Chrome version 54 and Safari, but didn't work on IE 11
what worked on them all
var obj = document.getElementById("pdfDoc");
obj.setAttribute('data', newPdf);
var cl = obj.cloneNode(true);
var parent = obj.parentNode;
parent.removeChild(obj);
parent.appendChild(cl);
This snippet did the job in my case
var object = document.getElementById(objectID);
object.setAttribute('data', newData);
var clone = object.cloneNode(true);
var parent = object.parentNode;
parent.removeChild(object );
parent.appendChild(clone );
<div id='myob'>
<object style="border: none;" standby="loading" id="contentarea"
width="100%" height="53%" type="text/html" data="test1.html"></object>
</div>
$('#myob').html($('#myob').html());
Changing the data attribute should be easy. However, it may not work perfectly on all browsers.
If the content is always HTML why not use an iframe?
Antoher way of doing it, you could embed the object in a DIV
var newUrl = 'http://example.com';
var divEl = document.getElementById('divID');
var objEl = document.getElementById('objID');
objEl.data = newUrl;
// Refresh the content
divEl.innerHTML = divEl.innerHTML;
I think this is a better way to achieve your objective.
Html:
<div id="mytemplate"><div>
Js:
function changeTemplate(t){
var mytemplate = document.getElementById("mytemplate");
mytemplate.innerHTML = '<object type="text/html" data=' + t + '></object>';
}
changeTemplate('template.html');
changeTemplate('whatever.html');
var content_area = document.getElementById("contentarea");
content_area.data = newUrl;
Refreshes object in Chrome Version 42.0.2311.90 m
the main reason of this issue is using "/" in local files.
The Wrong Code :
var obj = document.getElementById("hostedhtml");
obj.setAttribute('data', "pages\page2.html");
The Right Code :
var obj = document.getElementById("hostedhtml");
obj.setAttribute('data', "pages\\page2.html");