I have been trying to find the location of an attribute (line, column) in a specific xml node. I know i can reach the node and the attribute value by using XPATH or sax parser but havent found a way to locate the position of the attribute.
Appreciate your help
The DOM parsers found in browsers typically don't make any location information available (AFAIK). If you're using a third-party SAX parser then you may be more lucky; but it all depends on the parser you are using. I'd be surprised to see location information at the individual attribute level, though: it's expensive to provide, and element-level information is more common.
I managed to do this using XMLDOM.
DOMParser = require('xmldom').DOMParser;
var parser = new DOMParser({locator:{}});
var content = parser.parseFromString(xmlContent, "text/xml");
var rootNode = this.parseXml(content.documentElement);
var attrs = rootNode .attributes || [];
for (var i = 0; i < attrs.length; i++) {
var attr = attrs[i];
var nColumn = attr.columnNumber;
var nLine = attr.lineNumber;
}
For example, a sample XML file is:
<parents name='Parents'>
<Parent id='1' name='Parent_1'>
<Children name='Children'>
<child name='Child_2' id='2'>child2_Parent_1</child>
<child name='Child_4' id='4'>child4_Parent_1</child>
<child name='Child_1' id='3'>child1_Parent_1</child>
<child name='Child_3' id='1'>child3_Parent_1</child>
</Children>
</Parent>
<Parent id='2' name='Parent_2'>
<Children name='Children'>
<child name='Child_1' id='8'>child1_parent2</child>
<child name='Child_2' id='7'>child2_parent2</child>
<child name='Child_4' id='6'>child4_parent2</child>
<child name='Child_3' id='5'>child3_parent2</child>
</Children>
</Parent>
</parents>
Using XPath, you can do :
//Parent[#id='1']/Children/child/#name
Output :
Child_2
Child_4
Child_1
Child_3
Related
Is there a way to convert HTML like:
<div>
<span></span>
</div>
or any other HTML string into DOM element? (So that I could use appendChild()). I know that I can do .innerHTML and .innerText, but that is not what I want -- I literally want to be capable of converting a dynamic HTML string into a DOM element so that I could pass it in a .appendChild().
Update: There seems to be confusion. I have the HTML contents in a string, as a value of a variable in JavaScript. There is no HTML content in the document.
You can use a DOMParser, like so:
var xmlString = "<div id='foo'><a href='#'>Link</a><span></span></div>";
var doc = new DOMParser().parseFromString(xmlString, "text/xml");
console.log(doc.firstChild.innerHTML); // => <a href="#">Link...
console.log(doc.firstChild.firstChild.innerHTML); // => Link
You typically create a temporary parent element to which you can write the innerHTML, then extract the contents:
var wrapper= document.createElement('div');
wrapper.innerHTML= '<div><span></span></div>';
var div= wrapper.firstChild;
If the element whose outer-HTML you've got is a simple <div> as here, this is easy. If it might be something else that can't go just anywhere, you might have more problems. For example if it were a <li>, you'd have to have the parent wrapper be a <ul>.
But IE can't write innerHTML on elements like <tr> so if you had a <td> you'd have to wrap the whole HTML string in <table><tbody><tr>...</tr></tbody></table>, write that to innerHTML and extricate the actual <td> you wanted from a couple of levels down.
Why not use insertAdjacentHTML
for example:
// <div id="one">one</div>
var d1 = document.getElementById('one');
d1.insertAdjacentHTML('afterend', '<div id="two">two</div>');
// At this point, the new structure is:
// <div id="one">one</div><div id="two">two</div>here
Check out John Resig's pure JavaScript HTML parser.
EDIT: if you want the browser to parse the HTML for you, innerHTML is exactly what you want. From this SO question:
var tempDiv = document.createElement('div');
tempDiv.innerHTML = htmlString;
Okay, I realized the answer myself, after I had to think about other people's answers. :P
var htmlContent = ... // a response via AJAX containing HTML
var e = document.createElement('div');
e.setAttribute('style', 'display: none;');
e.innerHTML = htmlContent;
document.body.appendChild(e);
var htmlConvertedIntoDom = e.lastChild.childNodes; // the HTML converted into a DOM element :), now let's remove the
document.body.removeChild(e);
Here is a little code that is useful.
var uiHelper = function () {
var htmls = {};
var getHTML = function (url) {
/// <summary>Returns HTML in a string format</summary>
/// <param name="url" type="string">The url to the file with the HTML</param>
if (!htmls[url])
{
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", url, false);
xmlhttp.send();
htmls[url] = xmlhttp.responseText;
};
return htmls[url];
};
return {
getHTML: getHTML
};
}();
--Convert the HTML string into a DOM Element
String.prototype.toDomElement = function () {
var wrapper = document.createElement('div');
wrapper.innerHTML = this;
var df= document.createDocumentFragment();
return df.addChilds(wrapper.children);
};
--prototype helper
HTMLElement.prototype.addChilds = function (newChilds) {
/// <summary>Add an array of child elements</summary>
/// <param name="newChilds" type="Array">Array of HTMLElements to add to this HTMLElement</param>
/// <returns type="this" />
for (var i = 0; i < newChilds.length; i += 1) { this.appendChild(newChilds[i]); };
return this;
};
--Usage
thatHTML = uiHelper.getHTML('/Scripts/elevation/ui/add/html/add.txt').toDomElement();
Just give an id to the element and process it normally eg:
<div id="dv">
<span></span>
</div>
Now you can do like:
var div = document.getElementById('dv');
div.appendChild(......);
Or with jQuery:
$('#dv').get(0).appendChild(........);
You can do it like this:
String.prototype.toDOM=function(){
var d=document
,i
,a=d.createElement("div")
,b=d.createDocumentFragment();
a.innerHTML=this;
while(i=a.firstChild)b.appendChild(i);
return b;
};
var foo="<img src='//placekitten.com/100/100'>foo<i>bar</i>".toDOM();
document.body.appendChild(foo);
Alternatively, you can also wrap you html while it was getting converted to a string using,
JSON.stringify()
and later when you want to unwrap html from a html string, use
JSON.parse()
I need to write some html with placeholder used for javascript.
ex:
<span><placeholder data-id="42" data-value="abc"/><span>
Later on, a script will access those placeholders and put content in (next to?) them.
<span><placeholder data-id="42" data-value="abc"><div class="Google"><input type="text" value="abc"/></div><span>
But the placeholder tag doesn't exist. What tag can be used? Using < input type="hidden" .../> all over feels wrong.
Creating Custom tag
var xFoo = document.createElement('placeholder');
xFoo.innerHTML = "TEST";
document.body.appendChild(xFoo);
Output:
<placeholder>TEST</placeholder>
DEMO
Note: However creating hidden input fields with unique ID is good practice.
give your span element an id like,
<span id="placeToAddItem"><span>
and then in jQuery,
$('#placeToAddItem').html('<div class="Google"><input type="text" value="abc"/></div>');
or else
var cloneDiv = $('.Google');
$('#placeToAddItem').html(cloneDiv);
Example
The best way to do this, is using <input type='hidden' id="someId" value=""> tags.
Then you can easily access them by using jQuery, and recall the variable or change it.
var value = $("#someId").val(); to get variable or $("#someId").val(value) to change it.
This complete, no jQuery solution allows you to specify the placeholder/replacement html as a string within the element that will be replaced.
EG HTML:
<div data-placeholder="<div class='Google'><input type='text' value='abc'/></div>"></div>
<div data-placeholder="<div class='Boogle'><input type='text' value='def'/></div>"></div>
<div data-placeholder="<div class='Ooogle'><label>with label <input type='text' value='ghi'/></label></div>"></div>
<span data-placeholder="<em>Post JS</em>">Pre JS</span>
<br />
<button id="test">click me</button>
JS:
Use querySelectorAll to select all elements with the attribute 'data-placeholder' (returns a NodeList)
var placeholders = document.querySelectorAll('[data-placeholder]'); //or by ids, classnames, element type etc
Extend the NodeList prototype with a simple 'each' method that allows us to iterate over the list.
NodeList.prototype.each = function(func) {
for (var i = 0; i < this.length; i++) {
func(this[i]);
}
return this;//return self to maintain chainability
};
Extend the Object prototype with a 'replaceWith' method that replaces the element with a new one created from a html string:
Object.prototype.replaceWith = function(htmlString) {
var temp = document.createElement('div');//create a temporary element
temp.innerHTML = htmlString;//set its innerHTML to htmlString
var newChild = temp.childNodes[0];//(or temp.firstChild) get the inner nodes
this.parentNode.replaceChild(newChild, this);//replace old node with new
return this;//return self to maintain chainability
};
Put it all together:
placeholders.each(function(self){
self.replaceWith(self.dataset.placeholder);//the 'data-placeholder' string
});
Another example but here we only replace one specific element with some hard-coded html on click:
document.getElementById("test").addEventListener('click', function() {
this.replaceWith("<strong>i was a button before</strong>");
}, false);
DEMO: http://jsfiddle.net/sjbnn68e/
use the code below :
var x = document.createElement('placeholder');
x.innerHTML = "example";
document.body.appendChild(x);
How do i loop through the 'roster' tag, and push in to an array, if any 'player' node is found .
How do i check, no child elements in 'roster' tag .
I tried in the following way, but not working,
var strXML = '<root><club><roster/></club>\
<club><roster>
<player code="AUQ" name="AVDALOVIC, VULE" position="Guard"/>\
<player code="AQX" name="SCHULTZE, SVEN" position="Forward"/>\
</roster></club></root>';
var p = new DOMParser();
var doc = p.parseFromString(strXML, "application/xml");
var players=doc.getElementsByTagName("player");
var i=0,arr=[];
for(i=0;i<players.length;i++){
arr.push({
code:players[i].getAttribute("code"),
name:players[i].getAttribute("name"),
position:players[i].getAttribute("position"),
});
}
console.log(arr);
I am getting the output, but the output is coming blank, if any blank values are found.
Your xml has a problem, there should be one root element for the document
var strXML = '<root><club><roster/></club><club><roster><player code="AUQ" name="AVDALOVIC, VULE" position="Guard"/><player code="AQX" name="SCHULTZE, SVEN" position="Forward"/></roster></club></root>';
Demo: Fiddle
I am currently working with Jquery and my entire project needs to be done only using sharepoint Client Object Model (so i cant make use of server side coding). I have created a xml structure (by appending some string together) and stored it in a jquery var variable. Now my variable content looks like this
<Collection xmlns="http://schemas.microsoft.com/collection/metadata/2009"
xmlns:ui="http://schemas.microsoft.com/livelabs/pivot/collection/2009"
SchemaVersion="1" Name="listname">
<FacetCategories>
<FacetCategory Name="Title" Type="String" />
<FacetCategory Name="Created By" Type="String" />
<FacetCategory Name="Modified By" Type="String" />
</FacetCategories>
<Items ImgBase="http://460d87.dzc">
<Item Id="0" Img="#0" Name="Name1" Href="http://site/1_.000">
<Facets>
<Facet Name="Title">
<String Value="Name1" />
</Facet>
</Facets>
</Item>
</Items>
</collection>
I want to convert this variable in to xml content purely based on jquery.I have used ParseXml() Method but i'm not able to see the output in alert(). Please help me out with this.
Just use native built-in XML parser:
var parser, xml;
if (window.DOMParser) {
parser = new DOMParser();
xml = parser.parseFromString(str, "text/xml");
}
else { // IE
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = "false";
xml.loadXML(str);
}
var nodes = xml.getElementsByTagName('FacetCategory');
var i, l = nodes.length, items = [];
for (i = 0; i < l; i++) {
console.log(nodes[i].getAttribute('Name'));
}
http://jsfiddle.net/QqtMa/
Your xml is invalid, your root element is Collection but the closing tag is collection with small c, so the parser is failing
I'm trying to grab an xml node by its attribute.
edit
I'm trying to retrieve an element by its attribute value using javascript xml instead of jquery. Is there a simple method for this?
It is really easy using jQuery. Suppose we have a string like this.
<document>
<value type="people">
<name>
John
</name>
</value>
<value type="vehicle">
<name>
Ford
</name>
</value>
</document>
Then
var xmlDocument = $.parseXML(str);
$(xmlDocument).find("value[type='people'] name").text()
We will get string 'John' back.
You have to find a list of elements first, then filter by their attributes.
Check out my demo here: http://jsfiddle.net/silkster/eDP5V/
I feel this justifies a new answer as it is JQuery Free
document.getElementsByAttribute = function(attribute, value, tagName, parentElement) {
var children = ($(parentElement) || document.body).getElementsByTagName((tagName || '*'));
return $A(children).inject([], function(elements, child) {
var attributeValue = child.getAttribute(attribute);
if(attributeValue != null) {
if(!value || attributeValue == value) {
elements.push(child);
}
}
return elements;
});
}
source
it has been pointed out to me that I posted the wrong script.. hehe read here
// document.getElementsByAttribute([string attributeName],[string attributeValue],[boolean isCommaHyphenOrSpaceSeparatedList:false])
document.getElementsByAttribute=function(attrN,attrV,multi){
attrV=attrV.replace(/\|/g,'\\|').replace(/\[/g,'\\[').replace(/\(/g,'\\(').replace(/\+/g,'\\+').replace(/\./g,'\\.').replace(/\*/g,'\\*').replace(/\?/g,'\\?').replace(/\//g,'\\/');
var
multi=typeof multi!='undefined'?
multi:
false,
cIterate=document.getElementsByTagName('*'),
aResponse=[],
attr,
re=new RegExp(multi?'\\b'+attrV+'\\b':'^'+attrV+'$'),
i=0,
elm;
while((elm=cIterate.item(i++))){
attr=elm.getAttributeNode(attrN);
if(attr &&
attr.specified &&
re.test(attr.value)
)
aResponse.push(elm);
}
return aResponse;
}
jquery can do this very easily. http://think2loud.com/224-reading-xml-with-jquery/