source

.text()를 사용하여 하위 태그에 중첩되지 않은 텍스트만 검색

manysource 2023. 5. 10. 22:07

.text()를 사용하여 하위 태그에 중첩되지 않은 텍스트만 검색

HTML이 다음과 같은 경우:

<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

는 려하고합니다용사를 사용하려고 합니다..text() is text'라는 'This is some text'라고 하면 'This is some text', 'This is some text', 'This is some text', 'This is some text'.$('#list-item').text()"이것은 일부 텍스트입니다. 첫 번째 스팬 텍스트 첫 번째 스팬 텍스트 두 번째 스팬 텍스트"입니다.

다음과 같은 것을 통해 (그리고 가능하면 제거할 수 있는) 방법이 있습니까?.text("") 태그 하위 태그의 텍스트가 아닌 태그 내의 자유 텍스트만 사용할 수 없습니다.

HTML은 제가 작성한 것이 아니기 때문에 이것이 제가 작업해야 하는 것입니다.html을 작성할 때 텍스트를 태그로 포장하는 것이 간단하다는 것을 알지만, 역시 html은 미리 작성된 것입니다.

저는 다음을 기반으로 한 재사용 가능한 구현이 마음에 들었습니다.clone()부모 요소 내부의 텍스트만 가져오는 메서드입니다.

쉽게 참조할 수 있도록 제공된 코드:

$("#foo")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text();

간단한 대답:

$("#listItem").contents().filter(function(){ 
  return this.nodeType == Node.TEXT_NODE; 
})[0].nodeValue = "The text you want to replace with" 

8 Explorer를 .3Node.TEXT_NODE.

이것은 저에게 jquery를 과도하게 사용하는 경우처럼 보입니다.다음은 다른 노드를 무시하고 텍스트를 가져옵니다.

document.getElementById("listItem").childNodes[0];

당신은 그것을 다듬어야 할 것이지만, 그것은 당신이 원하는 것을 한 줄로 쉽게 얻을 수 있습니다.

편집

위의 내용은 텍스트 노드를 가져옵니다.실제 텍스트를 가져오려면 다음을 사용합니다.

document.getElementById("listItem").childNodes[0].nodeValue;

더 쉽고 빠르게:

$("#listItem").contents().get(0).nodeValue

승인된 답변과 유사하지만 복제하지 않은 경우:

$("#foo").contents().not($("#foo").children()).text();

이를 위한 jQuery 플러그인은 다음과 같습니다.

$.fn.immediateText = function() {
    return this.contents().not(this.children()).text();
};

이 플러그인을 사용하는 방법은 다음과 같습니다.

$("#foo").immediateText(); // get the text without children

코드가 아닌가요?

var text  =  $('#listItem').clone().children().remove().end().text();

그냥 jQuery를 위해 jQuery가 되는 건가요?단순한 작업에서 체인된 명령 수가 많고 (불필요한) 처리가 많이 필요한 경우 jQuery 확장자를 작성해야 할 때입니다.

(function ($) {
    function elementText(el, separator) {
        var textContents = [];
        for(var chld = el.firstChild; chld; chld = chld.nextSibling) {
            if (chld.nodeType == 3) { 
                textContents.push(chld.nodeValue);
            }
        }
        return textContents.join(separator);
    }
    $.fn.textNotChild = function(elementSeparator, nodeSeparator) {
    if (arguments.length<2){nodeSeparator="";}
    if (arguments.length<1){elementSeparator="";}
        return $.map(this, function(el){
            return elementText(el,nodeSeparator);
        }).join(elementSeparator);
    }
} (jQuery));

연락처:

var text = $('#listItem').textNotChild();

인수는 다음과 같은 다른 시나리오가 발생할 경우에 사용됩니다.

<li>some text<a>more text</a>again more</li>
<li>second text<a>more text</a>again more</li>

var text = $("li").textNotChild(".....","<break>");

텍스트 값:

some text<break>again more.....second text<break>again more

사용해 보십시오.

$('#listItem').not($('#listItem').children()).text()

여러분이 제시하는 구조에 따라 요구 사항에 맞는 것이 필요합니다.제공한 예제의 경우 다음과 같이 작동합니다.

$(document).ready(function(){
     var $tmp = $('#listItem').children().remove();
     $('#listItem').text('').append($tmp);
});

데모: http://jquery.nodnod.net/cases/2385/run

하지만 마크업이 당신이 게시한 것과 유사한지에 따라 상당히 다릅니다.

$($('#listItem').contents()[0]).text()

Stuart 답변의 짧은 변형입니다.

또는 와 함께get()

$($('#listItem').contents().get(0)).text()

선택한 요소의 직접 자식인 모든 텍스트 노드의 내용을 얻고 싶다면 이것도 좋은 해결책이 될 것입니다.

$(selector).contents().filter(function(){ return this.nodeType == 3; }).text();

참고: jQuery 설명서는 내용 함수를 설명하기 위해 유사한 코드를 사용합니다. https://api.jquery.com/contents/

추신. 좀 더 추잡한 방법도 있지만, 이것은 사물이 어떻게 작동하는지 더 자세히 보여주고 텍스트 노드 간에 사용자 지정 구분 기호를 사용할 수 있습니다(아마도 줄 바꿈을 원할 것입니다).

$(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join("");
jQuery.fn.ownText = function () {
    return $(this).contents().filter(function () {
        return this.nodeType === Node.TEXT_NODE;
    }).text();
};

가 약만그자가리인 경우index형제 노드 된 노드를 할 수 있습니다.

$('parentselector').contents().eq(index).text()

이것은 오래된 질문이지만 상위 답변은 매우 비효율적입니다.다음은 더 나은 솔루션입니다.

$.fn.myText = function() {
    var str = '';

    this.contents().each(function() {
        if (this.nodeType == 3) {
            str += this.textContent || this.innerText || '';
        }
    });

    return str;
};

이렇게 하면 됩니다.

$("#foo").myText();

나는 treeWalker를 사용하여 html 요소에 연결되지 않은 모든 텍스트 요소를 찾을 것을 제안합니다(이 함수는 jQuery를 확장하는 데 사용할 수 있습니다).

function textNodesOnlyUnder(el) {
  var resultSet = [];
  var n = null;
  var treeWalker  = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) {
    if (node.parentNode.id == el.id && node.textContent.trim().length != 0) {
      return NodeFilter.FILTER_ACCEPT;
    }
    return NodeFilter.FILTER_SKIP;
  }, false);
  while (n = treeWalker.nextNode()) {
    resultSet.push(n);
  }
  return resultSet;
}



window.onload = function() {
  var ele = document.getElementById('listItem');
  var textNodesOnly = textNodesOnlyUnder(ele);
  var resultingText = textNodesOnly.map(function(val, index, arr) {
    return 'Text element N. ' + index + ' --> ' + val.textContent.trim();
  }).join('\n');
  document.getElementById('txtArea').value = resultingText;
}
<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>
<textarea id="txtArea" style="width: 400px;height: 200px;"></textarea>

저는 특히 불필요한 요소 복제를 만드는 솔루션을 제외하고는 jQuery에 신경쓰지 않을 것입니다.텍스트 노드를 잡기만 하면 됩니다.현대 자바스크립트(이 글에서 "modern"은 움직이는 대상이다!)에서, 그리고 결과의 처음과 끝에서 공백을 자릅니다.

const { childNodes } = document.getElementById("listItem");
let text = "";
for (const node of childNodes) {
    if (node.nodeType === Node.TEXT_NODE) {
        text += node.nodeValue;
    }
}
text = text.trim();

실시간 예제:

const { childNodes } = document.getElementById("listItem");
let text = "";
for (const node of childNodes) {
    if (node.nodeType === Node.TEXT_NODE) {
        text += node.nodeValue;
    }
}
console.log(text);
<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

어떤 사람들은 사용할 것입니다.reduce이를 위하여저는 팬이 아닙니다. 간단한 루프가 더 명확하다고 생각하지만, 이 사용법은 각 반복에서 축적기를 업데이트하기 때문에 실제로 남용하지 않습니다. reduce:

const { childNodes } = document.getElementById("listItem");
const text = [...childNodes].reduce((text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const { childNodes } = document.getElementById("listItem");
const text = [...childNodes].reduce((text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();
console.log(text);
<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

또는 임시 배열을 만들지 않고도:

const { childNodes } = document.getElementById("listItem");
const text = Array.prototype.reduce.call(childNodes, (text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const { childNodes } = document.getElementById("listItem");
const text = Array.prototype.reduce.call(childNodes, (text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();
console.log(text);
<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

IE 9+ 호환 구문에서 몇 줄로 일반 JavaScript 사용:

const childNodes = document.querySelector('#listItem').childNodes;

if (childNodes.length > 0) {
    childNodesLoop:
    for (let i = 0; i < childNodes.length; i++) {
        //only target text nodes (nodeType of 3)
        if (childNodes[i].nodeType === 3) {
            //do not target any whitespace in the HTML
            if (childNodes[i].nodeValue.trim().length > 0) {
                childNodes[i].nodeValue = 'Replacement text';
                //optimized to break out of the loop once primary text node found
                break childNodesLoop;
            }
        }
    }
}

하위 요소의 텍스트 없이 요소의 모든 텍스트 가져오기는 2022년에도 여전히 중요하지 않은 작업으로 보입니다.
하지만 jQuery는 필요하지 않습니다.

모든 원시 textNode 컨텐츠를 가져오는 방법

const getElementTextWithoutChildElements = (el) =>
  Array.from(el.childNodes)               // iterator to array
    .filter(node => node.nodeType === 3)  // only text nodes
    .map(node => node.textContent)        // get text
    .join('')                             // stick together
;

또는 다음과 유사한 방법을 사용합니다.

const getElementTextWithoutChildElements = (el) =>
  [].reduce.call(
    el.childNodes, 
    (a, b) => a + (b.nodeType === 3 ? b.textContent : ''),
    ''
  );

이 작업을 수행해야 합니다.

<div>
  you get this
  <b>not this</b>
  you get this   too
</div>

반환됨:


  you get this

  you get this   too

요소 사이의 공백은 까다로울 수 있습니다. 예를 들어 .trim()과 함께 사용하거나 모든 공백을 정규화하는 것이 좋습니다.
요소를 신속하게 식별하기 위한 디버깅 및 로깅의 경우 일반적으로 이 정도면 충분합니다.

getElementTextWithoutChildElements(...).replace(/\s+/g, ' ').trim();
// 'you get this you get this too'

공백을 다르게 조정할 수도 있지만, 노드당 공백을 처리하는 축소() 함수 자체 내에서 가능합니다.

예: 노드당 공백 처리:

const getElementTextWithoutChildElements_2 = (el) =>
  Array.from(el.childNodes)
    .filter(node => node.nodeType === 3)
    .map(node => node.textContent.trim()) // added .trim()
    .join(',')                            // added ','
;

위 사항에 대한 빠른 테스트:

document.body.innerHTML = `
  you get this
  <b>not this</b>
  you get this   too
`;
// '\n  you get this\n  <b>not this</b>\n  you get this   too\n'

getElementTextWithoutChildElements(document.body);
// '\n  you get this\n  \n  you get this   too\n'

getElementTextWithoutChildElements(document.body).replace(/\s+/g, ' ').trim();
// 'you get this you get this too'

getElementTextWithoutChildElements_2(document.body);
// 'you get this,you get this   too'

이것은 나에게 좋은 방법입니다.

   var text  =  $('#listItem').clone().children().remove().end().text();

저는 복제 및 수정보다 훨씬 더 효율적이어야 하는 구체적인 해결책을 생각해냈습니다.이 솔루션은 다음 두 가지 예약에서만 작동하지만 현재 수락된 솔루션보다 더 효율적이어야 합니다.

  1. 당신은 오직 문자만 받고 있습니다.
  2. 추출할 텍스트가 하위 요소 앞에 있습니다.

그 말과 함께, 코드는 다음과 같습니다.

// 'element' is a jQuery element
function getText(element) {
  var text = element.text();
  var childLength = element.children().text().length;
  return text.slice(0, text.length - childLength);
}

라이브 데모

<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

<input id="input" style="width: 300px; margin-top: 10px;">

    <script type="text/javascript">
$("#input").val($("#listItem").clone().find("span").remove().end().text().trim());
    //use .trim() to remove any white space
    </script>

초보자용:

저는 @DUZUN의 답변이 수용된 답변보다 이해하기 쉽고 효율적이기 때문에 선호했습니다.하지만 이렇게 클래스 선택기로 요소를 직접 전달할 수 없기 때문에 부분적으로만 효과가 있었습니다.

$(".landing-center .articlelanding_detail").get(0).immediateText() //gives .immediateText is not a function error

또는 이

$(".landing-center .articlelanding_detail")[0].immediateText() //gives .immediateText is not a function error

왜냐하면 $() 함수에서 [index] 또는 .get(index)를 사용하여 네이티브 Element를 추출하면 여기서 언급한 것처럼 jQueryObject 메서드의 체인성이 느슨해지기 때문입니다.그리고 대부분의 솔루션은 ID에 대한 컨텍스트에서만 사용되며 클래스 선택기가 있는 요소에 대해 여러 번 사용하기에는 그리 우아하지 않습니다.

그래서 저는 jQuery 플러그인을 작성했습니다.

$.fn.mainText = function(x=0) {
    return $.trim(this.eq(x).contents().not(this.eq(x).children()).text().replace(/[\t\n]+/g,' '));
};

그러면 ID 또는 클래스가 하위 요소를 제외한 선택기로 사용되는지 여부에 관계없이 요소의 텍스트가 반환됩니다.또한 모든 항목을 제거합니다.\t or \n깨끗한 끈을 얻기 위해.다음과 같이 사용합니다.

사례 1

$("#example").mainText(); // get the text of element with example id

사례 2

$(".example").mainText(); // get the text of first element with example class

사례 3

$(".example").mainText(1); // get the text of second element with example class and so on..

JQuery가 없는 answer의 대체 버전

[...document.getElementById("listItem").childNodes].find(c => c.nodeType === Node.TEXT_NODE).nodeValue

텍스트를 추출하려고 , 과,즉▁my▁just▁(▁where내▁problems요부▁i▁elements소(▁inie했▁getting▁was,▁question▁inner▁text▁was▁but▁the▁some▁trying)에서 문제가 발생했습니다.<i>,<div>,<span>등)도 제거되고 있었습니다.

다음 코드는 잘 작동하고 나의 모든 문제를 해결한 것 같습니다.

여기에 제공된 답변 중 일부를 사용하지만 특히 요소가 다음과 같은 경우에만 텍스트를 대체합니다.nodeType === 3.

$(el).contents().each(function() { 
  console.log(" > Content: %s [%s]", this, (this.nodeType === 3));

  if (this.nodeType === 3) {
    var text = this.textContent;
    console.log(" > Old   : '%s'", text);

    regex = new RegExp("\\[\\[" + rule + "\\.val\\]\\]", "g");
    text = text.replace(regex, value);

    regex = new RegExp("\\[\\[" + rule + "\\.act\\]\\]", "g");
    text = text.replace(regex, actual);

    console.log(" > New   : '%s'", text);
    this.textContent = text;
  }
});

에서 하는 에서하 일주은모어진요위것의 을 순환시키는 입니다.el (으)로 것입니다.$("div.my-class[name='some-name']");각 내부 요소에 대해서는 기본적으로 무시합니다.텍스트의 각 부분에 대해(에 의해 결정됨)if (this.nodeType === 3)정규식 대체를 해당 요소에만 적용합니다.

this.textContent = text부분은 단순히 대체된 텍스트를 대체하며, 저의 경우, 저는 다음과 같은 토큰을 찾고 있었습니다.[[min.val]],[[max.val]] 타기.

이 짧은 코드 발췌문은 질문이 무엇을 요구했는지, 그리고 약간 더 많은 것을 시도하는 사람들에게 도움이 될 것입니다.

얼마나 유연하게 다루어야 하는지 또는 몇 개의 사례를 다루어야 하는지는 확실하지 않지만, 예를 들어, 텍스트가 항상 첫 번째 HTML 태그 앞에 온다면 첫 번째 태그에서 내부 HTML을 분할하고 전자를 취하는 것은 어떨까요?

$('#listItem').html().split('<span')[0]; 

그리고 더 넓게 필요하다면 그냥.

$('#listItem').html().split('<')[0]; 

그리고 두 마커 사이에 텍스트가 필요한 경우(예: 한 항목 뒤에 다른 항목 앞에) if 문을 사용하여 null ref 오류를 피하면서 시작 또는 끝 마커 또는 둘 다를 가질 수 있도록 유연하게 할 수 있습니다.

var startMarker = '';// put any starting marker here
var endMarker = '<';// put the end marker here
var myText = String( $('#listItem').html() );
// if the start marker is found, take the string after it
myText = myText.split(startMarker)[1];        
// if the end marker is found, take the string before it
myText = myText.split(endMarker)[0];
console.log(myText); // output text between the first occurrence of the markers, assuming both markers exist.  If they don't this will throw an error, so some if statements to check params is probably in order...

저는 일반적으로 이러한 유형의 문자열 조작을 항상 다시 작성하고 null 참조 등의 위험을 감수하는 것이 아니라 이러한 유용한 것들을 위해 유틸리티 기능을 만들고 오류가 없도록 만든 다음 솔리드가 되면 자주 사용합니다.이렇게 하면 많은 프로젝트에서 이 함수를 다시 사용할 수 있으며 문자열 참조에 정의되지 않은 참조 오류가 있는 이유를 다시 디버깅하는 데 시간을 낭비할 필요가 없습니다.지금까지 가장 짧은 1줄 코드는 아닐 수도 있지만, 유틸리티 기능을 사용한 후에는 그때부터 1줄이 됩니다.대부분의 코드는 오류를 피하기 위해 매개 변수를 처리하거나 처리하는 것입니다 :)

예:

/**
* Get the text between two string markers.
**/
function textBetween(__string,__startMark,__endMark){
    var hasText = typeof __string !== 'undefined' && __string.length > 0;
    if(!hasText) return __string;
    var myText = String( __string );
    var hasStartMarker = typeof __startMark !== 'undefined' && __startMark.length > 0 && __string.indexOf(__startMark)>=0;
    var hasEndMarker =  typeof __endMark !== 'undefined' && __endMark.length > 0 && __string.indexOf(__endMark) > 0;
    if( hasStartMarker )  myText = myText.split(__startMark)[1];
    if( hasEndMarker )    myText = myText.split(__endMark)[0];
    return myText;
}

// now with 1 line from now on, and no jquery needed really, but to use your example:
var textWithNoHTML = textBetween( $('#listItem').html(), '', '<'); // should return text before first child HTML tag if the text is on page (use document ready etc)

추가 조건을 사용하여 내부 여부 확인HTML과 innerText는 동일합니다.이러한 경우에만 텍스트를 바꿉니다.

$(function() {
$('body *').each(function () {
    console.log($(this).html());
    console.log($(this).text());
    if($(this).text() === "Search" && $(this).html()===$(this).text())  {
        $(this).html("Find");
    }
})
})

http://jsfiddle.net/7RSGh/

결과를 트리밍하려면 DotNetWala를 다음과 같이 사용합니다.

$("#foo")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text()
    .trim();

짧은 버전을 다음과 같이 사용한다는 것을 알게 되었습니다.document.getElementById("listItem").childNodes[0]jQuery의 트림()에서 작동하지 않습니다.

그냥 그것을 a에 넣으시오.<p>또는<font> 글꼴()$('#listItem 꼴글')를 가져옵니다.

가장 먼저 생각난 것은

<li id="listItem">
    <font>This is some text</font>
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

해보세요.

alert(document.getElementById('listItem').firstChild.data)

저는 농담 전문가는 아니지만, 어떻게 하면,

$('#listItem').children().first().text()

테스트되지 않았지만 다음과 같은 방법을 사용할 수 있습니다.

 $('#listItem').not('span').text();

http://api.jquery.com/not/

언급URL : https://stackoverflow.com/questions/3442394/using-text-to-retrieve-only-text-not-nested-in-child-tags