Reputation: 495
I have a list of keys and values and I intend to create an xml based on this information.
My list return:
1 person
2 information
3 name
3 surname
2 address
3 street
3 country
And I want to generate an xml:
<xml>
<person>
<information>
<name></name>
<surname></surname>
</information>
<address>
<street></street>
<country></country>
</address>
</person>
</xml>
I have a list of elements, while traversing these elements would create the xml document hierarchically. I already have this code:
var elements = document.getElementsByClassName('elements');
var xml = document.createElement('xml');
for (var i = 0; i < elements.length; i++) {
var key = elements[i].getAttribute('data-key');
var value = elements[i].getAttribute('data-value');
console.log(key +' -> '+ value);
// HERE: create new elements appendChild "var xml"
}
Upvotes: 0
Views: 45
Reputation: 147363
Very similar to Forty3's answer but a tad more concise and uses and XML document, not an HTML document.
Note that if document is an HTML document, then document.createElement changes the tagname to lower case, whereas if it's an XML document, the tag case is preserved. Also, in an HTML document it's reliant on support for custom and unknown tagnames, which might not be available, so better to use an XML document.
I've made up a data source, it seems it comes from the document so hopefully it reasonably approximate what you're using. I've put some minimal validation on the level, there should be more validation of the input to ensure it meets some standardised format.
function buildDoc() {
// Create an XML document to use to create the elements
var doc = document.implementation.createDocument(null, null, null);
var data = document.getElementsByClassName('elements');
var root = doc.createElement('xml');
var parent = root;
var level = 0;
var node, tagname;
for (var i=0, iLen=data.length; i<iLen; i++) {
dataNode = data[i];
node = doc.createElement(dataNode.dataset.value);
nodeLevel = dataNode.dataset.key;
// Can only add nodes at level 1 or higher
if (nodeLevel <= 0) {
console.log('Level ' + nodeLevel + ' is invalid. Can only create nodes at level 1 or higher');
return;
}
// If node at same level, is sibling of current parent
// If node at lower level, go back levels and parents to same level
// Append node, then make node the parent
if (nodeLevel <= level) {
while (nodeLevel < level) {
parent = parent.parentNode;
--level;
}
parent = parent.parentNode.appendChild(node);
// If node at higher level, is child of current parent
// Next node might higher again, so set parent to node
} else if (nodeLevel > level){
parent = parent.appendChild(node);
level = nodeLevel;
}
}
// Return the root
return root;
}
window.onload = function() {
console.log(buildDoc().outerHTML);
};
<div>
<span class="elements" data-key="1" data-value="Person">1 person</span><br>
<span class="elements" data-key="2" data-value="information">2 information</span><br>
<span class="elements" data-key="3" data-value="name">3 name</span><br>
<span class="elements" data-key="3" data-value="surname">3 surname</span><br>
<span class="elements" data-key="2" data-value="address">2 address</span><br>
<span class="elements" data-key="3" data-value="street">3 street</span><br>
<span class="elements" data-key="3" data-value="country">3 country</span><br>
<span class="elements" data-key="2" data-value="address">2 address</span><br>
<span class="elements" data-key="3" data-value="street">3 street</span><br>
<span class="elements" data-key="3" data-value="country">3 country</span><br>
</div>
PS. This probably won't run in IE 10 or lower due to lack of support for data-* attributes.
Upvotes: 1
Reputation: 2229
Note: this is untested and I need to step away. But, this should give you a starting point with comments.
var elements = document.getElementsByClassName('elements');
var xml = document.createElement('xml');
var curElem = xml;
var curDepth = 0;
for (var i = 0; i < elements.length; i++) {
var key = elements[i].getAttribute('data-key');
var value = elements[i].getAttribute('data-value');
console.log(key +' -> '+ value);
// HERE: create new elements appendChild "var xml"
// Create the new element
var elem = document.createElement(value);
// If we are further down the hierarchy, simply add the child
if (key > curDepth) {
curElem.appendChild(elem);
} else if (key == curDepth) {
// We are a sibling of our current containing element
// so simply add to the parent
curElem.parentElement.appendChild(elem);
curElem = elem;
} else if (key < curDepth) {
// We are at some point ABOVE our current element
// so start walking UP until we reach the level indicated
// and then add the element to the parent
while (curDepth >= key) {
curElem = curElem.parentElement;
curDepth--;
}
curElem.parentElement.appendChild(elem);
}
curElem = elem;
curDepth = key;
}
Upvotes: 1