Например: нацеливание на элемент контейнера (div # container) по id (getElementById) возвращает коллекцию HTML, содержащую каждый элемент и все его свойства, включая дочерние узлы, повторяемые в каждом вложенном элементе. Затем я повторяю каждый элемент в массиве, но у меня остаются одни и те же данные, повторяемые на каждом уровне дерева DOM.
0: <div class="container"><div><div><main><footer><div class="container-fluid"><p> © 2018-2020 Copyright: </p></div></footer></main></div></div></div>
1: <div><div><main><footer><div class="container-fluid"><p> © 2018-2020 Copyright: </p></div></footer></main></div></div>
2: <div><main><footer><div class="container-fluid"><p> © 2018-2020 Copyright: </p></div></footer></main></div>
3: <main><footer><div class="container-fluid"><p> © 2018-2020 Copyright: </p></div></footer></main>
4: <footer><div class="container-fluid"><p> © 2018-2020 Copyright: </p></div></footer>
5: <div class="container-fluid"><p> © 2018-2020 Copyright: </p></div>
6: <p> © 2018-2020 Copyright: </p>
То, что я хотел бы сделать, это захватить фактический контент только один раз (например, <p> © 2018-2020 Copyright: </p>
) - и связать его с соответствующим местоположением XPath - для повторной сборки HTML документ позже только с содержащимися выше структурами, содержащими теги и атрибуты элемента; только вставляя содержимое в последний дочерний узел узла, как показано ниже:
/DIV/DIV/DIV/MAIN/FOOTER/ --> `<div class="container-fluid"><p></p></div>`
/DIV/DIV/DIV/MAIN/FOOTER/DIV --> `<p></p>`
/DIV/DIV/DIV/MAIN/FOOTER/DIV/P --> © 2018-2020 Copyright:
Фон / контекст: Цель этого - уменьшить избыточность в моем объекте массива, чтобы создать эффективная полезная нагрузка (в конечном итоге преобразуемая в JSON) для отправки в Microsoft Translator API, так что я не буду без необходимости переводить одни и те же узлы контента, чтобы реконструировать переведенную страницу, вставляя ответный текст перевода обратно в исходное местоположение DOM, используя XPath и jQuery.
До сих пор я использовал jQuery и TreeWalker Web API (https://developer.mozilla.org/en-US/docs/Web/API/TreeWalker) для достижения sh того, что у меня есть до сих пор ...
JavaScript:
// Get all element nodes of page
var content = document.getElementById('container');
//array for DOM elements
var b = [];
function elementNodesUnder(el) {
var n;
nodeFilter = function(node) {
if (node.innerHTML && node.tagName !== 'SCRIPT' && node.tagName !==
'STYLE' && node.tagName !== 'svg' && node.tagName !== 'I' &&
node.tagName !== 'VIDEO') { return NodeFilter.FILTER_ACCEPT;
} else {
return NodeFilter.FILTER_SKIP;
}
};
walk = document.createTreeWalker(
el,
NodeFilter.SHOW_ELEMENT,
nodeFilter,
false
);
while ((n = walk.nextNode())) b.push(n);
return b;
}
elementNodesUnder(content);
console.log(b);
//array variables for xpath + innerHTML collections
var xPathArray = [];
var innerHTMLdinner = [];
//loop through text nodes & assign xPath
$.each(b, function(i, c) {
if (c.innerHTML) {
//console.log(i+" "+getElementXPath(c)+" = "+c.innerHTML);
//push each corresponding item to an array for xpath + innerHTML
xPathArray.push(getElementXPath(c));
innerHTMLdinner.push(c.innerHTML);
}
});
//map the xPath and innerHTML arrays together and then stringify
var xpathNodeMap = xPathArray.map((xPathers, index) => ({xPathArray: xPathers, innerHTML: innerHTMLdinner[index]}));
var xpathNodeMapJSON = JSON.stringify(xpathNodeMap);
console.log(xpathNodeMapJSON);
// given a document element returns the xpath string expression of that element.
function getElementXPath(elt) {
var path = '';
for (; elt && elt.nodeType == 1; elt = elt.parentNode) {
idx = getElementIdx(elt);
xname = elt.tagName;
if (idx > 1) xname += '[' + idx + ']';
path = '/' + xname + path;
}
return path;
}
function getElementIdx(elt) {
var count = 1;
for (var sib = elt.previousSibling; sib; sib = sib.previousSibling) {
if (sib.nodeType == 1 && sib.tagName == elt.tagName) count++;
}
return count;
}
HTML Пример :
<html>
<body>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div id="container">
<div class="layout">
<div class="bodyContainer">
<main class="wrapper">
<footer class="full-standard">
<div class="container no-print">
<div class="row">
<img alt="" src="" />
</div> <!-- footer > div.row -->
</div> <!-- /div.container.no-print -->
<div class="footer-copyright>
<div class="container-fluid">
<p>© 2020 Copyright</p>
</div> <!-- /div.container-fluid -->
</div> <!-- /div.footer-copyright -->
</footer> <!-- /footer.full-standard -->
</main> <!-- /main.wrapper -->
</div> <!-- /div.bodyContainer-->
</div> <!--/div.layout -->
</div> <!-- / div#container -->
</body>
</html>
Пример результатов XPath :
{
"xPathArray": "/HTML/BODY/DIV[6]/DIV/DIV/MAIN/FOOTER/DIV[2]",
"innerHTML": "<div class=\"container-fluid\"><p> © 2018-2020 Copyright: </p></div>"
},
{
"xPathArray": "/HTML/BODY/DIV[6]/DIV/DIV/MAIN/FOOTER/DIV[2]/DIV",
"innerHTML": "<p> © 2018-2020 Copyright: </p>"
},
{
"xPathArray": "/HTML/BODY/DIV[6]/DIV/DIV/MAIN/FOOTER/DIV[2]/DIV/P",
"innerHTML": " © 2018-2020 Copyright: "
}
Удивительно, но я не смог найти что-то слишком близкое к этому вопросу, поэтому я прошу прощения, если я пропустил его, но любая помощь, чтобы указать мне в правильном направлении, была бы чрезвычайно признательна. Спасибо!