I'm currently struggling with trying to build out a function that should take an input object from parsing HTML5 ( node-html5-parser
) and I need to process all tags and children tags, with their content to output a string of xml. The issue I'm running into is how to get a recursive function (or any function) to properly maintain the HTML5 tag order and outputting the content.
Example:
<div><span>My Content</span></div>
With the node-html5-parser, I get the following when it parses that:
rootElem {
childNodes: [
{
tagName: 'div',
childNodes: [
{
tagName: 'span',
childNodes: [
{
rawText: 'My Content'
}
],
}
]
}
]
}
I thought a simple DFS recursive algorithm could be used to build up a string, but I can't get it to work correctly.
const DOMRootObj = parse(this.htmlStr);
const processedData = this.processContent(DOMRootObj);
processContent(root: any): string {
if (root && !root.childNodes.length) {
return root.rawText;
} else {
for (const childNode of root.childNodes) {
const str = this.processContent(childNode);
const { tagName } = childNode;
if (tagName) {
this.outputStr += `<${tagName}>${str}</${tagName}>`;
}
}
}
}
from this HTML that's parsed by the parse() function: (object is as above)
<div><span>My Content</span></div>
This ends up outputting:
<span>undefined</span><div>undefined</div>
but It should output:
<div><span>My Content</span></div>
Not sure which XML format you expect, but the recursive call is not that hard to implement:
function toString(node, name="root") { let tag = typeof name === "string"? name: node.tagName; return tag? `<${tag}>${(node.childNodes||[]).map(toString).join``}</${tag}>`: (node.rawText || ""); } // Sample: let rootElem = { childNodes: [{ tagName: 'div', childNodes: [{ tagName: 'span', childNodes: [{ rawText: 'My Content' }], }] }] }; console.log(toString(rootElem, "root"));
Ive got a few days some same kind of problem inside a browsere. I want to walk over a dom tree and execute a function with given parameters on the nodes. In my case i want to reassign the element id if any. Thats why the function is named nodeinit. Anyhow
function nodeinit(node,dataset){console.log(node);}
function shadowWalker(node, nodeinit, dataset) {
nodeinit(node, dataset);
if (node) {
console.log(node.id);
if (node.childNodes.length > 0) {
node = node.firstChild; //needed to init while loop
while (node) {
shadowWalker(node, nodeinit, dataset);
node = node.nextSibling;
}
}
}
}
So its called with the node to start of. Nodeinit is a function and dataset is the parameter object for the nodeinit function (some kind of presets). Some similar answers you can find here by looking for transverse dom tree. Just as a idea or starting point.
Unpolished code, but you can get the ideia. You can add more attributes like onclick and tabindex simply by repeating the pattern. Although I don't think putting everything on the generator a good idea (you can lose track of what's being generated).
fillHeaderCurrenciesList = () => {
// Generated structure example
// <div
// id='currency-1'
// class='currency currency--hoverable'
// onclick='selectMainCurrency(this.id)'
// >
// <div class='currency__name'>Bitcoin</div>
// <div class='currency__icon'>
// <img src='assets/img/icon-coin.svg' alt='LG Bank' />
// <img src='assets/img/icon-btc.svg' alt='LG Bank' />
// </div>
// <div class='currency__balance'>
// <span class='currency__title'>Balance</span>
// <div class='currency__value'>
// <span>Exemplo1 | R$ 234.342.367,90</span>
// </div>
// </div>
// </div>;
let currenciesList = document.getElementById('currencies-list');
for (let i = 0; i < currencyData.length; i++) {
const currency = currencyData[i];
let currencyTree = {
tagName: 'div',
id: `currency-${i}`,
class: ['currency', 'currency--hoverable'],
onClick: function () {
selectMainCurrency(this, 'currencies-main-currency');
},
onKeyDown: function () {
keyDownEnter(
selectMainCurrency(this, 'currencies-main-currency')
);
},
tabIndex: '0',
children: [
{
tagName: 'div',
class: ['currency__name'],
text: currency.name,
},
{
tagName: 'div',
class: ['currency__icon'],
children: [
{
tagName: 'img',
src: currency.icon.src,
alt: currency.icon.alt,
},
{
tagName: 'img',
src: currency.iconName.src,
alt: currency.iconName.alt,
},
],
},
{
tagName: 'div',
class: ['currency__balance'],
children: [
{
tagName: 'span',
class: ['currency__title'],
text: 'Balance',
},
{
tagName: 'div',
class: ['currency__value'],
children: [
{
tagName: 'span',
text: currency.balance,
},
],
},
],
},
],
};
currenciesList.appendChild(DOMListItemGenerator(currencyTree));
}
};
const currencyData = [
{
name: 'bitcoin',
icon: {
src: 'assets/img/icon-coin.svg',
alt: 'LG Bank',
},
iconName: {
src: 'assets/img/icon-btc.svg',
alt: 'LG Bank',
},
quotation: '',
balance: 'Exemplo1bitcoin | R$ 234.342.367,90',
},
{
name: 'ethereum',
icon: {
src: 'assets/img/icon-coin.svg',
alt: 'LG Bank',
},
iconName: {
src: 'assets/img/icon-btc.svg',
alt: 'LG Bank',
},
quotation: '',
balance: 'Exemplo2ethereum | R$ 234.342.367,90',
},
{
name: 'ethereum',
icon: {
src: 'assets/img/icon-coin.svg',
alt: 'LG Bank',
},
iconName: {
src: 'assets/img/icon-btc.svg',
alt: 'LG Bank',
},
quotation: '',
balance: 'Exemplo2ethereum | R$ 234.342.367,90',
},
{
name: 'ethereum',
icon: {
src: 'assets/img/icon-coin.svg',
alt: 'LG Bank',
},
iconName: {
src: 'assets/img/icon-btc.svg',
alt: 'LG Bank',
},
quotation: '',
balance: 'Exemplo2ethereum | R$ 234.342.367,90',
},
{
name: 'teste',
icon: {
src: 'assets/img/icon-coin.svg',
alt: 'LG Bank',
},
iconName: {
src: 'assets/img/icon-btc.svg',
alt: 'LG Bank',
},
quotation: '',
balance: 'Exemplo3teste | R$ 234.342.367,90',
},
];
fillHeaderCurrenciesList();
DOMListItemGenerator = (inputTree) => {
let tree = Object.entries(inputTree);
let item;
let output;
for (let i = 0; i < tree.length; i++) {
const branch = tree[i];
if (branch[0] === 'tagName') {
output = document.createElement(branch[1]);
}
if (branch[0] === 'id') {
output.setAttribute('id', branch[1]);
}
if (branch[0] === 'tabIndex') {
output.setAttribute('tabindex', branch[1]);
}
if (branch[0] === 'class') {
for (const classItem of branch[1]) {
output.classList.add(classItem);
}
}
if (branch[0] === 'src') {
output.src = branch[1];
}
if (branch[0] === 'alt') {
output.alt = branch[1];
}
if (branch[0] === 'text') {
output.textContent = branch[1];
}
if (branch[0] === 'onClick') {
output.onclick = branch[1];
}
if (branch[0] === 'onKeyDown') {
output.onkeydown = branch[1];
}
if (branch[0] === 'children' && branch[1].length > 0) {
for (let j = 0; j < branch[1].length; j++) {
const children = branch[1][j];
item = DOMListItemGenerator(children);
output.appendChild(item);
}
}
}
return output;
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.