How to update a parsed xml value - javascript

I'm parsing an XML as an object and accessing nodes by tagname, I have a problem where the value I'd like to see updated doesn't get updated. The alert shows me the value and it is correct. But i need it to be displayed on the document and which it isn't.
var x = xml.responseXML;
var v1 = document.getElementById("sid");
alert(x.getElementsByTagName("ID")[0].childNodes[0].nodeValue);
v1.innerText = x.getElementsByTagName("ID")[0].childNodes[0].nodeValue;
I also have a question of how can I allow editing/highlight of the node?

If nodeValue is null, setting its value has no effect (from the docs). However, you can modify the XML content in other ways, for example .innerHTML, .innerText, .value and more. Example with .innerHTML:
// creates a Document, as in XMLHttpRequest.responseXML
const docText = `
<!DOCTYPE html>
<body>
<div>Hello</div>
<div>World</div>
</body>`;
const doc = (new DOMParser()).parseFromString(docText, 'application/xml');
// setting nodeValue over null has no effect...
console.log(doc.getElementsByTagName('div')[0].nodeValue);
doc.getElementsByTagName('div')[0].nodeValue = 'Bye';
console.log(doc.getElementsByTagName('div')[0].nodeValue);
// ...but you can modifies the XML in different ways
console.log(doc.getElementsByTagName('div')[0].innerHTML);
doc.getElementsByTagName('div')[0].innerHTML = 'Bye';
console.log(doc.getElementsByTagName('div')[0].innerHTML);

Related

Parse HTML String to DOM and convert it back to string

I've got an HTML string e.g. '<p><span class="text">Hello World!</span></p>'
I parse this HTML string to DOM using DOMParser().parseFromString(), because I want to change the innerHTML of some specific elements. That's why I parse the HTML string to DOM and with getElementByClassName I get all my elements and loop through them to change it innerHTML. This works so far.
After I changed the innerHTML, I try to convert the new DOM back to a string. I can't figure out how. What I tried is to assign the innerHTML or outerHTML (tried both) to a variable like this:
const parser = new DOMParser();
const doc = parser.parseFromString("<p>Hello World!</p>", "text/html");
console.log(doc.innerHTML) // undefined
console.log(doc.outerHTML) // undefined
const parser = new DOMParser();
const doc = parser.parseFromString("<p>Hello World!</p>", "text/html");
console.log(doc.innerHTML) // undefined
console.log(doc.outerHTML) // undefined
I always get undefined. How can I parse it back to a string? I found a lot examples with innerHTML or outerHTML, but in my case something went wrong. Any ideas?
DOMParser will always give you a document in return. Documents don't have an innerHTML property, but the document.documentElement does, just like in a page's normal document object:
const myHtmlString = '<p><span class="text">Hello World!</span></p>'
const htmlDom = new DOMParser().parseFromString(myHtmlString, 'text/html');
console.log(htmlDom.documentElement.innerHTML);
Do note that a <head> and <body> will be created for you, if you don't pass those tags in yourself. If you only want the body, then:
const myHtmlString = '<p><span class="text">Hello World!</span></p>'
const htmlDom = new DOMParser().parseFromString(myHtmlString, 'text/html');
console.log(htmlDom.body.innerHTML);

Finding and replacing html tags conditionally from an html string

I have access to an html string in which I want to search for a specific set of values. So lets say I want to match something from an array...
var array1 = [value1, value2, value3]
If I find value1 in the html string, i want to add a highlight class to that value so it gets highlighted.
var str = htmlString
var res = str.replace('<thead>','<thead class="highlight">');
htmlString = res
Using this i can highlight all the theads, but how could I write it so that I only highlight the theads that contain one of those array values inside of it?
Here's a solution for browser that parses the HTML string into a DOM element, query the DOM tree and manipulate the classList of each selected element, then returns the HTML as a string.
function addClassToElementsByTagName(html, tagName, className) {
var tempElement = document.createElement('div');
tempElement.innerHTML = html;
var elements = tempElement.querySelectorAll(tagName);
elements.forEach(function(element) {
element.classList.add(className);
});
return tempElement.innerHTML;
}
var htmlString = '<table>\n\t<thead>\n\t<tr>\n\t\t<th>Column 1</th>\n\t\t<th>Column 2</th>\n\t\t<th>Column 3</th>\n\t</tr>\n\t</thead>\n</table>';
var result = addClassToElementsByTagName(htmlString, 'thead', 'highlight');
console.log(result);
Gotchas
Keep in mind that element.querySelectorAll() and element.classList.add() are not universally supported. Check out caniuse.com for information regarding each feature.
Also, this is completely dependent on how the browser parses your HTML. If the HTML fails to parse or parses incorrectly, you will experience problems. The .innerHTML property also makes no guarantee that the whitespace provided in the original string will be preserved in the result.

Cross-browser innerText for setting values

Let's say I have the following code:
<html>
<head></head>
<body>
<div id="d">some text</div>
<script type="text/javascript">
var d = document.getElementByid('d');
var innerText = d.innerText || d.textContent;
innerText = 'new text';
</script>
</body>
</html>
And I want to change text value for the div tag with id='d'. Unfortunately the block code above doesn't work and the text content doesn't change.
It works if do the following recipe:
if (d.innerText) d.innerText = 'new text';
else d.textContent = 'new text';
But I dont like the recipe above because it's not compact.
Have you any suggestions why the first approach doesn't work?
Instead of multiple assignments, you can grab the property and use that
var text = ('innerText' in d)? 'innerText' : 'textContent';
d[text] = 'New text';
The first approach doesn't work because all it does is set the variable to the new value, it doesn't write the value to the element. The line
var innerText = d.innerText || d.textContent;
...sets the variable innerText to the value of the text property it finds, it's not a reference to the actual property itself.
You'll have to do the branch, e.g.:
var d = document.getElementById('d');
var msg = "new text";
if ("innerText" in d) {
d.innerText = msg;
}
else {
d.textContent = msg;
}
That feature-detects whether the browser uses innerText or textContent by looking for the existence of the property on the element (that's what the in operator does, check if an object has a property with the given name, even if that property is blank, null, undefined, etc.).
You can even write yourself a function for it:
var setText = (function() {
function setTextInnerText(element, msg) {
element.innerText = msg;
}
function setTextTextContent(element, msg) {
element.textContent = msg;
}
return "innerText" in document.createElement('span') ? setTextInnerText : setTextTextContent;
})();
That does the feature-detection once, and returns a function any half-decent engine will inline for you.
Or alternately, if you want HTML markup in the message to be handled as markup (rather than literal text), you can just use innerHTML (which is consistent across browsers). But again, if you use innerHTML, markup will be processed which may not be what you want.
I find it useful to use a good JavaScript library to deal with these browser differences (and to provide a ton of useful further functionality), such as jQuery, YUI, Closure, or any of several others. Obviously there's nothing you can do with a library you can't do without one, it's just a matter of standing on the shoulders of people who've done a huge amount of work already. :-)
In this case, for instance, using jQuery the above would be:
$("#d").text("new text");
That's it.
d.appendChild(document.createTextNode("new text");
you can use textContent only & it will work in major browsers... (FF, Safari & Chrome)
var d = document.getElementById('d');
var msg = "new text";
d.textContent = msg;

Html collection has a .length but undefined .item(*)

I have a function that calls to an xml page, picks out elements by the tag names, and I'm trying to call back a specific one. code so far is:
var xmlDoc = loadXMLDoc("test.xml");
var x = xmlDoc.getElementsByTagName("tagname");
var PittWins = x.item(2);
This will come back [object element]
var xmlDoc = loadXMLDoc("test.xml");
var x = xmlDoc.getElementsByTagName("tagname");
var PittWins = x[2].data;
The above code gives me undefined.
var xmlDoc = loadXMLDoc("nhl.xml");
var x = xmlDoc.getElementsByTagName("tagname");
var PittWins = x.length;
when entered above, i get a result which is correct.
I am trying to understand why it's giving me a length and not a specific node..
What about var PittWins = x[2];?
Re: OP edit
You're saying that x.item(2) and x.length return what you expect, but x[2].data does not? Why do you expect the element to have a data property? Are you trying to write the bracketed version of x.item(2)?
x.item(2) is equivalent to x[2].
x.item(2).data is equivalent to x[2].data.
What are you trying to do? Also, you've used different XML file names and tag names across your different examples. Is this intentional?
Edit #2
To retrieve the text content of an element, use Node.textContent or Node.nodeValue. Your code might look like this, then:
var PittWins = x[2].textContent;

javascript getElementById and convert it to String

is there a way to convert a javascript HTML object to a string?
i.e.
var someElement = document.getElementById("id");
var someElementToString = someElement.toString();
thanks a lot in advance
If you want a string representation of the entire tag then you can use outerHTML for browsers that support it:
var someElementToString = someElement.outerHTML;
For other browsers, apparently you can use XMLSerializer:
var someElement = document.getElementById("id");
var someElementToString;
if (someElement.outerHTML)
someElementToString = someElement.outerHTML;
else if (XMLSerializer)
someElementToString = new XMLSerializer().serializeToString(someElement);
You can always wrap a clone of an element in an 'offscreen', empty container.
The container's innerHTML is the 'outerHTML' of the clone- and the original.
Pass true as a second parameter to get the element's descendents as well.
document.getHTML=function(who,deep){
if(!who || !who.tagName) return '';
var txt, el= document.createElement("div");
el.appendChild(who.cloneNode(deep));
txt= el.innerHTML;
el= null;
return txt;
}
someElement.innerHTML
As Darin Dimitrov said you can use element.innerHTML to display the HTML element childnodes HTML. If you are under IE you can use the outerHTML propoerty that is the element plus its descendants nodes HTML
You just have to create one variable then store value into it. As in one my project I have done the same thing and it works perfectly.
var message = "";
message = document.getElementById('messageId').value;
test it.. It will definitely work.

Categories