요소의 텍스트 노드를 가져오는 방법?
<div class="title">
I am text node
<a class="edit">Edit</a>
</div>
나는 "나는 텍스트 노드"를 얻고 싶고, "편집" 태그를 제거하고 싶지 않으며, 크로스 브라우저 솔루션이 필요합니다.
var text = $(".title").contents().filter(function() {
return this.nodeType == Node.TEXT_NODE;
}).text();
이거는.contents
선택한 요소에 필터 함수를 적용합니다.필터 함수는 텍스트 노드(즉, 다음과 같은 노드)만 반환합니다.nodeType == Node.TEXT_NODE
).
첫 번째 자식 노드의 nodeValue를 가져올 수 있습니다.
$('.title')[0].childNodes[0].nodeValue
"복잡한" 또는 깊게 중첩된 요소에 유용할 수 있는 또 다른 네이티브 JS 솔루션은 NodeIterator를 사용하는 것입니다.NodeFilter.SHOW_TEXT
두 번째 인수("WhatToShow")로 요소의 텍스트 노드 자식에 대해서만 반복합니다.
var root = document.querySelector('p'),
iter = document.createNodeIterator(root, NodeFilter.SHOW_TEXT),
textnode;
// print all text nodes
while (textnode = iter.nextNode()) {
console.log(textnode.textContent)
}
<p>
<br>some text<br>123
</p>
사용할 수도 있습니다.TreeWalker
. 그 둘의 차이점은NodeIterator
단순한 선형 반복기인 반면TreeWalker
형제 및 조상을 통해서도 탐색할 수 있습니다.
첫 번째 #text 노드 내용을 반환하는 ES6 버전
const extract = (node) => {
const text = [...node.childNodes].find(child => child.nodeType === Node.TEXT_NODE);
return text && text.textContent.trim();
}
요소에서 첫 번째 텍스트 노드의 값을 구한다는 뜻이라면 이 코드는 다음과 같이 작동합니다.
var oDiv = document.getElementById("MyDiv");
var firstText = "";
for (var i = 0; i < oDiv.childNodes.length; i++) {
var curNode = oDiv.childNodes[i];
if (curNode.nodeName === "#text") {
firstText = curNode.nodeValue;
break;
}
}
이 내용은 http://jsfiddle.net/ZkjZJ/ 에서 확인할 수 있습니다.
순수 자바스크립트:미니멀리스트
우선, DOM에서 텍스트를 찾을 때는 항상 이 점을 유의해야 합니다.
이 문제는 XML/HTML의 구조에 주의를 기울일 것입니다.
이 순수한 자바스크립트 예에서, 저는 다른 종류의 노드와 인터리빙될 수 있는 여러 개의 텍스트 노드의 가능성을 설명합니다.그러나 처음에는 공백에 대한 판단을 전달하지 않고 필터링 작업을 다른 코드에 맡깁니다.
이 버전에서, 나는 A를 통과합니다.NodeList
호출/클라이언트 코드에서 입력합니다.
/**
* Gets strings from text nodes. Minimalist. Non-robust. Pre-test loop version.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @param nodeList The child nodes of a Node, as in node.childNodes.
* @param target A positive whole number >= 1
* @return String The text you targeted.
*/
function getText(nodeList, target)
{
var trueTarget = target - 1,
length = nodeList.length; // Because you may have many child nodes.
for (var i = 0; i < length; i++) {
if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) {
return nodeList[i].nodeValue; // Done! No need to keep going.
}
}
return null;
}
물론 테스트를 통해node.hasChildNodes()
첫째, 사전 테스트를 사용할 필요가 없을 것입니다.for
고리.
/**
* Gets strings from text nodes. Minimalist. Non-robust. Post-test loop version.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @param nodeList The child nodes of a Node, as in node.childNodes.
* @param target A positive whole number >= 1
* @return String The text you targeted.
*/
function getText(nodeList, target)
{
var trueTarget = target - 1,
length = nodeList.length,
i = 0;
do {
if ((nodeList[i].nodeType === Node.TEXT_NODE) && (i === trueTarget)) {
return nodeList[i].nodeValue; // Done! No need to keep going.
}
i++;
} while (i < length);
return null;
}
순수 자바스크립트: 강건함
여기서 함수getTextById()
는 두 가지 도우미 기능을 사용합니다.getStringsFromChildren()
그리고.filterWhitespaceLines()
.
자식에서 문자열 가져오기()
/**
* Collects strings from child text nodes.
* Generic, cross platform solution. No string filtering or conditioning.
*
* @author Anthony Rutledge
* @version 7.0
* @param parentNode An instance of the Node interface, such as an Element. object.
* @return Array of strings, or null.
* @throws TypeError if the parentNode is not a Node object.
*/
function getStringsFromChildren(parentNode)
{
var strings = [],
nodeList,
length,
i = 0;
if (!parentNode instanceof Node) {
throw new TypeError("The parentNode parameter expects an instance of a Node.");
}
if (!parentNode.hasChildNodes()) {
return null; // We are done. Node may resemble <element></element>
}
nodeList = parentNode.childNodes;
length = nodeList.length;
do {
if ((nodeList[i].nodeType === Node.TEXT_NODE)) {
strings.push(nodeList[i].nodeValue);
}
i++;
} while (i < length);
if (strings.length > 0) {
return strings;
}
return null;
}
필터백공간선()
/**
* Filters an array of strings to remove whitespace lines.
* Generic, cross platform solution.
*
* @author Anthony Rutledge
* @version 6.0
* @param textArray a String associated with the id attribute of an Element.
* @return Array of strings that are not lines of whitespace, or null.
* @throws TypeError if the textArray param is not of type Array.
*/
function filterWhitespaceLines(textArray)
{
var filteredArray = [],
whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression.
if (!textArray instanceof Array) {
throw new TypeError("The textArray parameter expects an instance of a Array.");
}
for (var i = 0; i < textArray.length; i++) {
if (!whitespaceLine.test(textArray[i])) { // If it is not a line of whitespace.
filteredArray.push(textArray[i].trim()); // Trimming here is fine.
}
}
if (filteredArray.length > 0) {
return filteredArray ; // Leave selecting and joining strings for a specific implementation.
}
return null; // No text to return.
}
TextById() 가져오기
/**
* Gets strings from text nodes. Robust.
* Generic, cross platform solution.
*
* @author Anthony Rutledge
* @version 6.0
* @param id A String associated with the id property of an Element.
* @return Array of strings, or null.
* @throws TypeError if the id param is not of type String.
* @throws TypeError if the id param cannot be used to find a node by id.
*/
function getTextById(id)
{
var textArray = null; // The hopeful output.
var idDatatype = typeof id; // Only used in an TypeError message.
var node; // The parent node being examined.
try {
if (idDatatype !== "string") {
throw new TypeError("The id argument must be of type String! Got " + idDatatype);
}
node = document.getElementById(id);
if (node === null) {
throw new TypeError("No element found with the id: " + id);
}
textArray = getStringsFromChildren(node);
if (textArray === null) {
return null; // No text nodes found. Example: <element></element>
}
textArray = filterWhitespaceLines(textArray);
if (textArray.length > 0) {
return textArray; // Leave selecting and joining strings for a specific implementation.
}
} catch (e) {
console.log(e.message);
}
return null; // No text to return.
}
다음으로 반환 값(Array 또는 null)이 처리되어야 하는 클라이언트 코드로 전송됩니다.배열에는 공백 줄이 아닌 실제 텍스트의 문자열 요소가 있어야 합니다.
빈 문자열(""
유효한 텍스트가 있음을 제대로 나타내려면 텍스트 노드가 필요하므로 반환되지 않습니다.복귀()""
)는 텍스트 노드가 존재한다는 잘못된 인상을 줄 수 있으며, 누군가가 다음의 값을 변경함으로써 텍스트를 변경할 수 있다고 가정하게 합니다..nodeValue
. 빈 문자열의 경우 텍스트 노드가 존재하지 않으므로 이는 거짓입니다.
예 1:
<p id="bio"></p> <!-- There is no text node here. Return null. -->
예 2:
<p id="bio">
</p> <!-- There are at least two text nodes ("\n"), here. -->
문제는 HTML을 띄어 읽기 쉽게 만들고 싶을 때 발생합니다.이제, 사람이 읽을 수 있는 유효한 텍스트가 없더라도, 그들의 텍스트 노드에는 여전히 새 "\n"
줄() 문자가 있습니다..nodeValue
특성.
인간은 예제 1과 2를 기능적으로 동등한 것으로 봅니다. 빈 요소들이 채워지기를 기다리고 있는 것입니다.DOM은 인간의 추론과는 다릅니다.이것이 그 이유입니다.getStringsFromChildren()
함수는 텍스트 노드가 존재하는지 확인하고 수집해야 합니다..nodeValue
배열에 값을 입력합니다.
for (var i = 0; i < length; i++) {
if (nodeList[i].nodeType === Node.TEXT_NODE) {
textNodes.push(nodeList[i].nodeValue);
}
}
예 2에서 두 개의 텍스트 노드가 존재하며getStringFromChildren()
돌려줄 것입니다..nodeValue
둘 다 ()"\n"
). 단,filterWhitespaceLines()
정규식을 사용하여 순수 공백 문자의 행을 걸러냅니다.
돌아옵니다null
새 줄 대신("\n"
) 문자는 클라이언트 / 호출 코드에 거짓말을 하는 형태?인간적인 면에서는 아닙니다.DOM 용어로는 그렇습니다.그러나 여기서 문제는 텍스트를 받는 것이지 편집하는 것이 아닙니다.호출 코드로 돌아갈 휴먼 텍스트가 없습니다.
누군가의 HTML에 몇 개의 새 줄 문자가 나타날 수 있는지 결코 알 수 없습니다. "두 번째" 새 줄 문자를 찾는 카운터를 만드는 것은 신뢰할 수 없습니다.존재하지 않을 수도 있습니다.
물론 더 아래로 가면 빈 텍스트 편집 문제가 발생합니다.<p></p>
공백이 추가된 요소(슬라이스 2)는 요소가 표시해야 할 내용을 정확하게 포함하도록 문단의 태그 사이에 하나의 텍스트 노드를 제외한 모든 텍스트 노드를 삭제( 건너뛸 수 있음)하는 것을 의미할 수 있습니다.
그럼에도 불구하고, 특별한 일을 하는 경우를 제외하고는, 어떤 텍스트 노드의 것을 결정할 수 있는 방법이 필요할 것입니다..nodeValue
속성에는 편집하고자 하는 사람이 읽을 수 있는 진실된 텍스트가 있습니다.filterWhitespaceLines
우리를 반쯤 데려다 줄 겁니다
var whitespaceLine = /(?:^\s+$)/; // Non-capturing Regular Expression.
for (var i = 0; i < filteredTextArray.length; i++) {
if (!whitespaceLine.test(textArray[i])) { // If it is not a line of whitespace.
filteredTextArray.push(textArray[i].trim()); // Trimming here is fine.
}
}
이 시점에서 다음과 같은 출력이 나타날 수 있습니다.
["Dealing with text nodes is fun.", "Some people just use jQuery."]
이두 DOM 이 한다는 은 에서 은 한다는 이 따라서 이 두 문자열을 연결합니다..join()
부자연스러운 합성물이 될 수도 있습니다대신에, 전화하는 코드에서getTextById()
, , , , .
출력을 테스트합니다.
try {
var strings = getTextById("bio");
if (strings === null) {
// Do something.
} else if (strings.length === 1) {
// Do something with strings[0]
} else { // Could be another else if
// Do something. It all depends on the context.
}
} catch (e) {
console.log(e.message);
}
하나는 추가할 수 있습니다..trim()
에의 getStringsFromChildren()
및 공백을 하는 방법(을 0 하는 방법)""
), 텍스트( 문자열)가되면 모든 프로그램이 일이 알 수 ?), 되면 이 해야 이 인지 에 에 인지 ?그렇지 않으니 특정 구현에 맡기고,getStringsFromChildren()
범속하다
이러한 수준의 특정성이 있을 때가 있을 수 있습니다.target
필요하지 않습니다. 경우에는 합니다.그런 경우에는 간단한 솔루션을 사용합니다.그러나 일반화된 알고리즘을 사용하면 단순하고 복잡한 상황을 수용할 수 있습니다.
$('.title').clone() //clone the element
.children() //select all the children
.remove() //remove all the children
.end() //again go back to selected element
.text(); //get the text of element
간단히 바닐라 자바스크립트를 통해:
const el = document.querySelector('.title');
const text = el.firstChild.textContent.trim();
공백도 무시되므로 빈 텍스트 노드가 없습니다.핵심 자바스크립트를 이용한 코드.
var oDiv = document.getElementById("MyDiv");
var firstText = "";
for (var i = 0; i < oDiv.childNodes.length; i++) {
var curNode = oDiv.childNodes[i];
whitespace = /^\s*$/;
if (curNode.nodeName === "#text" && !(whitespace.test(curNode.nodeValue))) {
firstText = curNode.nodeValue;
break;
}
}
jsfiddle 에서 확인하기 : - http://jsfiddle.net/webx/ZhLep/
XPath's를 사용할 수도 있습니다.text()
텍스트 노드만 가져오는 노드 테스트.를 들면
var target = document.querySelector('div.title');
var iter = document.evaluate('text()', target, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE);
var node;
var want = '';
while (node = iter.iterateNext()) {
want += node.data;
}
튼튼하지 않은 여객기가 있습니다.
Array.from(document.querySelector("#title").childNodes).find(n => n.nodeType == Node.TEXT_NODE).textContent
해결책이 몇 가지 은 에는 이 은 하는 만큼 만큼 하는 .childNodes
모든 노드 유형의 아이들을 얻고,.filter
를 e.nodeType === Node.TEXT_NODE
"빈" 노드 공백. 선택적으로 재귀적으로 수행하거나 "빈" 텍스트 노드(모든 공백)를 무시할 수도 있습니다.
이러한 예제는 표시 목적으로 노드를 텍스트 컨텐츠로 변환하지만, 이는 필터링과는 엄밀히 별개의 단계입니다.
const immediateTextNodes = el =>
[...el.childNodes].filter(e => e.nodeType === Node.TEXT_NODE);
const immediateNonEmptyTextNodes = el =>
[...el.childNodes].filter(e =>
e.nodeType === Node.TEXT_NODE && e.textContent.trim()
);
const firstImmediateTextNode = el =>
[...el.childNodes].find(e => e.nodeType === Node.TEXT_NODE);
const firstImmediateNonEmptyTextNode = el =>
[...el.childNodes].find(e =>
e.nodeType === Node.TEXT_NODE && e.textContent.trim()
);
// example usage:
const text = el => el.textContent;
const p = document.querySelector("p");
console.log(immediateTextNodes(p).map(text));
console.log(immediateNonEmptyTextNodes(p).map(text));
console.log(text(firstImmediateTextNode(p)));
console.log(text(firstImmediateNonEmptyTextNode(p)));
// if you want to trim whitespace:
console.log(immediateNonEmptyTextNodes(p).map(e => text(e).trim()));
<p>
<span>IGNORE</span>
<b>IGNORE</b>
foo
<br>
bar
</p>
a에 대한 재귀적 대안:
const deepTextNodes = el => [...el.childNodes].flatMap(e =>
e.nodeType === Node.TEXT_NODE ? e : deepTextNodes(e)
);
const deepNonEmptyTextNodes = el =>
[...el.childNodes].flatMap(e =>
e.nodeType === Node.TEXT_NODE && e.textContent.trim()
? e : deepNonEmptyTextNodes(e)
);
// example usage:
const text = el => el.textContent;
const p = document.querySelector("p");
console.log(deepTextNodes(p).map(text));
console.log(deepNonEmptyTextNodes(p).map(text));
<p>
foo
<span>bar</span>
baz
<span><b>quux</b></span>
</p>
마지막으로 텍스트 노드 배열을 사용하려면 자유롭게 문자열에 연결합니다..join("")
저는 필요에 입니다. 하지만 트리밍이나 텍스트 콘텐츠 추출과 마찬가지로, 저는 아마 이것을 핵심 필터링 기능으로 굽지 않고, 필요에 따라 처리하도록 발신자에게 맡기지는 않을 것입니다.
언급URL : https://stackoverflow.com/questions/6520192/how-to-get-the-text-node-of-an-element
'programing' 카테고리의 다른 글
C의 Const 배열 (0) | 2023.09.13 |
---|---|
wp_get_attachment_image에 속성 추가 (0) | 2023.09.13 |
세션에 목록 저장 (0) | 2023.09.08 |
문자열을 문자별로 반복하는 방법 (0) | 2023.09.08 |
(x < 0)과 (x == -1) 중 어느 것이 더 빠릅니까? (0) | 2023.09.08 |