Извлечение частичного текста (перед ) с помощью getElementsByClassName

#javascript #html #getelementsbyclassname #outerhtml

#javascript #HTML #getelementsbyclassname #outerhtml

Вопрос:

У меня возникли проблемы с извлечением определенного фрагмента текста из атрибута класса. Текст имеет как имя, так и идентификатор. Оба важны для меня, но мне нужно, чтобы они были разделены и помещены в отдельные массивы.

 <span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span>
 

Моей первой мыслью было удалить последний элемент в каждом элементе (преобразовать в строку или список, разделить символом » » и удалить последний элемент). Но я понял, что между именем и идентификатором не всегда есть пробел, поэтому это не работает.

Моей второй мыслью было использовать outerHTML и захватить все до <br> , а затем сделать то же самое с идентификатором после <br> .

Однако именно так выглядит возвращаемый текст, который использует outerHTML:

 "amp;<span class=amp;quot;locDescriptionamp;quot;amp;>amp;<bamp;>Name1amp;</bamp;>amp;<bramp;>ID1amp;</spanamp;>"
 

Я не мог найти способ просто захватить перед <br> … это казалось бы чем-то, что можно было бы сделать легко… может быть, я что-то упускаю.

Вместо этого я попытался использовать индексацию для захвата текста:

 var product_name = []
var elements = document.getElementsByClassName('locDescription');
for(var i=0; i<elements.length; i  ) product_name.push(elements[i].outerHTML)

test1 = product_name[0].indexOf('amp;>amp;<bamp;>')

console.log(test1)
 

Это вернулось как -1, поэтому оно не интерпретирует искажения в этом тексте. Есть идеи, как я могу это сделать? Я думаю, что в данный момент я спускаюсь в кроличью нору.

Комментарии:

1. const bs = document.querySelectorAll('.locDescription>b'); for(let b of bs){ console.log(b.textContent); }

2. Похоже, вы забыли ‘R’ из «br» в вашем .indexOf() : 'amp;>amp;<bamp;>'

Ответ №1:

Селектор запросов и дочерние узлы

 const spans = [...document.querySelectorAll(".locDescription")];
const details = spans.map(span => {
  const name = span.querySelector("b").textContent;
  const id = span.childNodes[2].nodeValue;
  return { name, id };
});
console.log(details); 
 <span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span> 

 const spans = Array.from(document.querySelectorAll(".locDescription"));
const details = spans.map(function(span){
  const name = span.querySelector("b").textContent;
  const id = span.childNodes[2].nodeValue;
  return { name: name, id: id };
});
console.log(details); 
 <span class="locDescription"><b>Name1</b><br> ID1</span>
<span class="locDescription"><b>Name2</b><br>ID2</span>
<span class="locDescription"><b>Name3</b><br> ID3</span> 

Комментарии:

1. Это работает отлично! К сожалению, GTM не позволяет использовать функции Spread или arrow? Возможно ли добиться того же с помощью другого метода?

Ответ №2:

Вы можете использовать свойства .previousSibling и .nextSibling узла, эти свойства включают в себя и другие узлы, то есть текстовые узлы.

Обратите внимание, что вам может потребоваться trim() .textContent указать другие нужные вам узлы, поскольку .textContent возвращает текст в том виде, в каком он написан в вашем HTML после экранирования кодов HTML-имен, что означает включение пробелов и разрывов строк, если таковые имеются.

Вот краткий пример:

  1. Запрос для <br>
  2. Использование .previousSibling / .nextSibling
  3. Получить их .textContent
  4. (Необязательно) trim() возвращаемый текст
 var brElement = document.querySelector('br');

console.log(brElement.previousSibling.textContent.trim());
console.log(brElement.nextSibling.textContent.trim()); 
 <p><b>First text</b><br>
Second text</p> 

Ответ №3:

Вы можете использовать регулярное выражение, чтобы найти две стороны:

 var element = document.getElementsByClassName("locDescription")[0];
var array = [];
array[0] = element.innerHTML.match(/.*(?=<br>)/)[0];
array[1] = element.innerHTML.match(/(?<=<br>).*/)[0];
console.log(array) 
 <span class="locDescription"><b>Name1</b><br> ID1</span> 

Если вы хотите исключить <b> теги:

 var element = document.getElementsByClassName("locDescription")[0];
var array = [];
array[0] = element.innerHTML.match(/(?<=<b>).*(?=</b>)/)[0]
array[1] = element.innerHTML.match(/(?<=<br>).*/)[0];
console.log(array) 
 <span class="locDescription"><b>Name1</b><br> ID1</span>