[英]Recursive Function to Create DOM Tree String from DOM Object
我目前正在努力構建一個 function,它應該從解析 HTML5 ( node-html5-parser
) 中獲取輸入 object,我需要處理所有標簽和子標簽,它們的內容為 output xml 的字符串。我遇到的問題是如何獲得遞歸 function(或任何函數)以正確維護 HTML5 標簽順序並輸出內容。
例子:
<div><span>My Content</span></div>
使用 node-html5-parser,我在解析時得到以下信息:
rootElem {
childNodes: [
{
tagName: 'div',
childNodes: [
{
tagName: 'span',
childNodes: [
{
rawText: 'My Content'
}
],
}
]
}
]
}
我認為可以使用簡單的 DFS 遞歸算法來構建字符串,但我無法使其正常工作。
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}>`;
}
}
}
}
從這個 HTML 由 parse() function 解析:(對象如上)
<div><span>My Content</span></div>
這最終輸出:
<span>undefined</span><div>undefined</div>
但它應該是 output:
<div><span>My Content</span></div>
不確定您期望哪種 XML 格式,但遞歸調用並不難實現:
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"));
我在瀏覽器中遇到了幾天類似的問題。 我想遍歷 dom 樹並在節點上使用給定參數執行 function。 在我的情況下,我想重新分配元素 ID(如果有)。 這就是為什么 function 被命名為 nodeinit。 無論如何
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;
}
}
}
}
因此,它與要啟動的節點一起調用。 Nodeinit 是 function 和 dataset 是 nodeinit function 的參數 object (某種預設)。 您可以通過尋找橫向 dom 樹在這里找到一些類似的答案。 只是作為一個想法或起點。
未經修飾的代碼,但你可以得到ideia。 您只需重復該模式即可添加更多屬性,例如 onclick 和 tabindex。 盡管我不認為將所有內容都放在生成器上是個好主意(您可能會忘記正在生成的內容)。
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;
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.