Как можно получить содержимое элемента DOM только один раз, если выбрать целое дерево, которое также содержит те же вложенные элементы? - PullRequest
0 голосов
/ 20 февраля 2020

Например: нацеливание на элемент контейнера (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>&copy; 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: "
}

Удивительно, но я не смог найти что-то слишком близкое к этому вопросу, поэтому я прошу прощения, если я пропустил его, но любая помощь, чтобы указать мне в правильном направлении, была бы чрезвычайно признательна. Спасибо!

1 Ответ

0 голосов
/ 20 февраля 2020

Попробуйте присвоить элементу, которому вы хотите, уникальный идентификатор - затем захватите этот элемент с помощью идентификатора и передадите innerText этого элемента вашему обработчику?

   <p id='unique_id'> Some Text </p>

    document.getElementbById('unique_id')[0].innerHTML

вам, возможно, придется поиграть с этим прикосновением, но общая идея должна работать

...