天道酬勤,学无止境

DOM TreeWalker to return all text nodes

I'm trying to get access to all text nodes within a given element, so that I can isolate words and wrap them in spans.

TreeWalker seems to be the API for the job, but I'm finding it to be extremely unintuitive. Neither the spec nor the MDN reference (usually so good at explaining arcane DOM APIs) are self-evident to my eyes.

My first assumption was that all I needed to pass was the right filter as second argument - something like document.createTreeWalker( element, NodeFilter.TEXT_NODE ). But this seems to stop as soon as it encounters a non-text node:

wordWrap( document.body )

function wordWrap( element ){
  var nodes = document.createTreeWalker( element, NodeFilter.TEXT_NODE )
  var node
  var text
  var word

  while( node = nodes.nextNode() ){
    text = node.nodeValue.replace( /(^\s+|\s+$)/, '' ).split( /\s+/g )

    while( text.length ){
      word = document.createElement( 'span' )

      word.className = 'word'

      word.innerText = text.shift()

      node.parentNode.insertBefore( word, node )

      if( text.length )
        node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
        }

    node.parentNode.removeChild( node )
  }
}
.word {
  background: #fee;
  padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions &#38; other enquiries.

So I assume this is an opportunity to use the third filter argument of the TreeWalker, as well as the extra properties on NodeFilter. If a filter method's valid return values are FILTER_ACCEPT, FILTER_REJECT & FILTER_SKIP, then I reason that by accepting element nodes as well as text nodes in the second argument, I can specify that text nodes should be accepted and the rest skipped. But this seems to give the same results - no text nodes are picked up within or after the anchor:

wordWrap( document.body )

function wordWrap( element ){
  var nodes = document.createTreeWalker(
    element,
    NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
    { acceptNode : function( node ){
      if( node.nodeType === node.TEXT_NODE )
        return NodeFilter.FILTER_ACCEPT
      else 
        return NodeFilter.FILTER_SKIP
    } } 
  )
  var node
  var text
  var word

  while( node = nodes.nextNode() ){
    text = node.nodeValue.replace( /(^\s+|\s+$)/, '' ).split( /\s+/g )

    while( text.length ){
      word = document.createElement( 'span' )

      word.className = 'word'

      word.innerText = text.shift()

      node.parentNode.insertBefore( word, node )

      if( text.length )
        node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
        }

    node.parentNode.removeChild( node )
  }
}
.word {
  background: #fee;
  padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions &#38; other enquiries.

By this point I'm convinced recursively iterating through the tree using DOM1 methods would be easier, like in this snippet:

wordWrap( document.body )

function wordWrap( element ){
  textNodes( element ).forEach( function( node ){
    var text = node.nodeValue.split( /\s+/g )
    var word

    while( text.length ){
      word = document.createElement( 'span' )

      word.className = 'word'

      word.innerText = text.shift()

      node.parentNode.insertBefore( word, node )

      if( text.length )
        node.parentNode.insertBefore( document.createTextNode( ' ' ), node )
        }

    node.parentNode.removeChild( node )
  } )
}

function textNodes( element ){
  var nodes = []

  Array.prototype.forEach.call( element.childNodes, function( child ){
    if( child.nodeType === child.TEXT_NODE )
      nodes = nodes.concat( child )
      else if( child.nodeType === child.ELEMENT_NODE )
        nodes = nodes.concat( textNodes( child ) )
        } )

  return nodes
}
.word {
  background: #fee;
  padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email@example.com</a> for submissions &#38; other enquiries.

What am I missing?

标签

评论

What am I missing?

node.parentNode.removeChild(node) is the problem - you're removing the current node from the DOM, so the walker will find no .nextNode() from the there.

You should either advance the walker before removing the node, or just not remove it and instead shrink its content (to what is left over when you've moved out all words).

wordWrap(document.body);

function wordWrap( element ){
  var nodes = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, null, null);
  var node;
  while (node = nodes.nextNode()) {
    var p = node.parentNode;
    var text = node.nodeValue;
    var m;
    while(m = text.match(/^(\s*)(\S+)/)) {
      text = text.slice(m[0].length);
      p.insertBefore(document.createTextNode(m[1]), node);
      var word = p.insertBefore(document.createElement('span'), node);
      word.appendChild(document.createTextNode(m[2]));
      word.className = 'word';
    }
    node.nodeValue = text;
  }
}
.word {
  background: #faa;
  padding: 0 .5em 0 0;
}
Contact us at <a href="mailto:email@example.com">email @ example.com</a> for submissions &#38; other enquiries.

Notice that the correct filter is NodeFilter.SHOW_TEXT, not .TEXT_NODE, and that in older browser the four arguments are not optional.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • DOM遍历 Nodeiterator和TreeWalker
    DOM遍历DOM遍历模块定义了用于辅助完成顺序遍历DOM结构的类型:Nodeiterator和TreeWalker,它们能够基于给定的起点对DOM结构执行深度优先(depth-first)的遍历操作。本文将详细介绍DOM遍历[注意]IE8-浏览器不支持定义DOM遍历是深度优先的DOM结构遍历,遍历以给定节点为根,不可能向上超出DOM树的根节点。以下面的HTML页面为例<!DOCTYPE html> <html> <head> <title>Example</title> </head> <body> <p><b>Hello</b> world!</p> </body> </html>下图展示了这个页面的DOM树任何节点都可以作为遍历的根节点,如果假设<body>元素为根节点,那么遍历的第一步就是访问<p>元素,然后再访问同为<body>元素后代的两个文本节点。不过,这次遍历永远不会到达<html>、<head>元素,也不会到达不属于<body>元素子树的任何节点。而以document为根节点的遍历则可以访问到文档中的全部节点下图展示了对以document为根节点的DOM树进行深度优先遍历的先后顺序从document开始依序向前,访问的第一个节点是document,访问的最后一个节点是包含"world!"的文本节点。从文档最后的文本节点开始,遍历可以反向移动到DOM树的顶端。此时
  • 等效于textNodes的getElementsByTagName()(getElementsByTagName() equivalent for textNodes)
    问题 有什么方法可以获取文档中所有textNode对象的集合? getElementsByTagName()非常适合Elements,但textNode不是Elements。 更新:我意识到这可以通过遍历DOM来完成-如以下建议所示。 我知道如何编写一个DOM-walker函数来查看文档中的每个节点。 我希望有一些浏览器本机的方法可以做到这一点。 毕竟,我可以通过单个内置调用来获取所有<input> ,但并非所有textNode都textNode 。 回答1 更新: 我已经概述了这6种方法在1000次运行中的每种的一些基本性能测试。 getElementsByTagName是最快的,但是它完成了一半工作,因为它不选择所有元素,而是仅选择一种特定类型的标记(我认为p ),并且盲目地假定其firstChild是文本元素。 它可能没有什么缺陷,但是它只是出于演示目的,并将其性能与TreeWalker进行了比较。 自行在jsfiddle上运行测试以查看结果。 使用TreeWalker 自定义迭代遍历自定义递归遍历 Xpath查询 querySelectorAll getElementsByTagName 让我们暂时假设有一种方法可以让您本地获取所有Text节点。 您仍然必须遍历每个结果文本节点并调用node.nodeValue以获取实际文本,就像处理任何DOM节点一样。 因此
  • 在uiwebview中使用javascript将样式应用于文本范围(apply style to range of text with javascript in uiwebview)
    问题 我在iPhone上的UIWebView中将一些简单样式的文本显示为html。 它基本上是一系列段落,偶尔带有强或强调的短语。 在运行时,我需要将样式应用于文本范围。 有几种类似的情况,其中一种是突出显示搜索结果。 如果用户搜索了“某物”,我想更改单词出现后的背景颜色,然后再恢复原始背景。 是否可以使用javascript将样式应用于文本范围? 其中的关键部分还在于可以取消设置样式。 似乎有两种可能的方法。 一种方法是在Objective-C中修改一些html,并通过javascript作为某些容器的新innerHTML进行传递。 另一种方法是使用javascript直接操作DOM节点。 我可以操纵html,但这在Objective-C中听起来很乏味,因此,如果那是一种合理的方法,我宁愿操纵DOM。 我对javascript和DOM不太熟悉,所以我不知道这是否是一种合理的方法。 我编写了一些例程来在文本范围和带有偏移量的节点范围之间进行转换。 因此,如果我从100-200的文本范围开始,并在一个段落中开始,在第三段中结束,则可以获取文本节点以及代表给定文本范围的节点中的偏移量。 我只需要一种在文本的偏移处拆分文本节点的方法。 目前,我只是将样式应用于包含文本范围的段落。 一些注意事项: 请直接使用javascript,没有像jquery这样的外部框架。 更改永远不需要写入磁盘。
  • innerHTML:如何避免(innerHTML: How To Avoid)
    问题 我正在编写一个插件,可以将表情符号转换为特定网站的文本块中的图像。 简单的答案是使用正则表达式来检测innerHTML上的触发文本并插入img标签,然后将字符串通过管道传递回innerHTML部分中的dom元素。 DOM元素块在innerHTML部分中可能已经具有锚点<a>和/或文本格式<b>,<i>,<u> 。 例如 var textBlock = pItems[i].innerHTML; var kissSource = 'https://mail.google.com/mail/e/35D'; textBlock = textBlock.replace(/(^|[^<]|[^>]):\*/g, "<img class='emoticon' src='" + kissSource + "' />"); --> pItems[i].innerHTML = textBlock; //<-can I avoid this to be in compliance with Mozilla addons reqmnts 我搜索了好几个小时,以了解如何将DOM(或HTML字符串)转换为XML(我知道:HTML!= XLM如何将HTML读取为XML?但也许是div的一部分?),这可能是转换为JSON,然后可以将..转换为以下内容的DOM:https://developer
  • 如何获取所有突出显示的元素(How to get all elements that are highlighted)
    问题 我想在用户突出显示的区域中获取所有元素。 问题是,当元素位于树的不同部分时,我不知道如何遍历DOM的不同部分。 到目前为止,我的代码只能使元素脱离选择范围的startContainer。 我需要某种递归吗? 这是我的代码: getSelectedElementTags:function() { var range, sel, container; sel = content.window.getSelection(); if (sel.getRangeAt) { if (sel.rangeCount > 0) { range = sel.getRangeAt(0); } } else { range = content.window.createRange(); range.setStart(sel.anchorNode, sel.anchorOffset); range.setEnd(sel.focusNode, sel.focusOffset); alert("range created"); } if (range) { container = range["startContainer"]; var elms = container.parentNode.getElementsByTagName("*"); elmlist = "parent: "+container
  • 相当于jQuery的本机Javascript:contains()选择器(Native javascript equivalent of jQuery :contains() selector)
    问题 我正在编写一个UserScript,它将从包含特定字符串的页面中删除元素。 如果我正确理解jQuery的contains()函数,则似乎是完成此工作的正确工具。 不幸的是,由于我将在其上运行UserScript的页面不使用jQuery,所以不能使用:contains()。 你们中任何一个可爱的人都知道这样做的本机方法是什么? http://codepen.io/coulbourne/pen/olerh 回答1 这应该在现代浏览器中执行: function contains(selector, text) { var elements = document.querySelectorAll(selector); return [].filter.call(elements, function(element){ return RegExp(text).test(element.textContent); }); } 然后像这样使用它: contains('p', 'world'); // find "p" that contain "world" contains('p', /^world/); // find "p" that start with "world" contains('p', /world$/i); // find "p" that end with
  • 保存和还原content的插入符位置(Saving and Restoring caret position for contentEditable div)
    问题 我有一个contentEditable div,它的innerHTML可以在编辑时通过AJAX进行更新。 问题是,当您更改div的内容时,它将光标移动到div的末尾(或失去焦点,具体取决于浏览器)。 有什么跨浏览器的好解决方案,可以在更改innerHTML之前存储插入符的位置,然后再将其还原? 回答1 回到2016年:) 在遇到此解决方案之后,它不适合我,因为每次输入后,我的DOM都会完全替换。 我已经进行了更多的研究,并提供了简单的解决方案,该解决方案通过对我来说非常合适的角色位置来节省光标。 想法很简单。 在插入符之前找到字符的长度并保存。 更改DOM。 使用TreeWalker仅在context node text nodes上行走并计数字符,直到获得正确的text node及其内部的位置 两个边缘情况: 内容已完全删除,因此没有text node : 所以:将光标移动到上下文节点的开始内容比index指向的要少: 所以:将光标移动到最后一个节点的末尾 function saveCaretPosition(context){ var selection = window.getSelection(); var range = selection.getRangeAt(0); range.setStart( context, 0 ); var len = range
  • 如何通过innerText获取元素(How to get element by innerText)
    问题 如果我知道文本标签包含什么内容,如何在html页面中获取标签。 例如: <a ...>SearchingText</a> 回答1 您将不得不手动遍历。 var aTags = document.getElementsByTagName("a"); var searchText = "SearchingText"; var found; for (var i = 0; i < aTags.length; i++) { if (aTags[i].textContent == searchText) { found = aTags[i]; break; } } // Use `found`. 回答2 您可以使用xpath完成此操作 var xpath = "//a[text()='SearchingText']"; var matchingElement = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; 您还可以使用以下xpath搜索包含一些文本的元素: var xpath = "//a[contains(text(),'Searching')]"; 回答3 使用当前可用的最现代语法,可以很干净地完成此操作: for
  • Javascript Contenteditable-将Cursor / Caret设置为索引(Javascript Contenteditable - set Cursor / Caret to index)
    问题 我该如何修改它(如何在contenteditable元素(div)中设置插入符(光标)的位置?),使其接受数字索引和元素,并将光标位置设置为该索引? 例如:如果我有以下段落: <p contenteditable="true">This is a paragraph.</p> 我打电话给: setCaret($(this).get(0), 3) 光标将移动到索引3,如下所示: Thi|s is a paragraph. 我有这个,但是没有运气: function setCaret(contentEditableElement, index) { var range,selection; if(document.createRange)//Firefox, Chrome, Opera, Safari, IE 9+ { range = document.createRange();//Create a range (a range is a like the selection but invisible) range.setStart(contentEditableElement,index); range.collapse(true); selection = window.getSelection();//get the selection object (allows
  • 如何获取元素的文本节点?(How to get the text node of an element?)
    问题 <div class="title"> I am text node <a class="edit">Edit</a> </div> 我希望获得“我是文本节点”,不希望删除“ edit”标签,并且需要跨浏览器解决方案。 回答1 var text = $(".title").contents().filter(function() { return this.nodeType == Node.TEXT_NODE; }).text(); 这将获取所选元素的contents ,并对其应用过滤功能。 筛选器功能仅返回文本节点(即,那些节点类型为nodeType == Node.TEXT_NODE节点)。 回答2 您可以使用以下方法获取第一个childNode的nodeValue: $('.title')[0].childNodes[0].nodeValue http://jsfiddle.net/TU4FB/ 回答3 如果您要获取元素中第一个文本节点的值,则此代码将起作用: var oDiv = document.getElementById("MyDiv"); var firstText = ""; for (var i = 0; i < oDiv.childNodes.length; i++) { var curNode = oDiv.childNodes[i]; if
  • 获取包含HTML内容的contentEditable区域中的插入符(光标)位置(Get caret (cursor) position in contentEditable area containing HTML content)
    问题 我有contentEditable元素(可以是p,div,...),我想在其中获得插入符号(光标)的位置。 我通常可以通过以下代码来实现: var position = window.getSelection().getRangeAt(0).startOffset; 当元素仅包含文本时,这可以很好地工作。 但是,当元素包含某些HTML格式时,返回的位置将相对于所包含HTML元素内的插入符号位置。 假设contentEditable元素的内容是这样的: AB<b>CD</b>EF 如果插入符号位于<b></b> ,那么在C和D之间说,上面代码返回的位置是1而不是3(从contentEditable元素内容的开头算起) 有人可以提出解决方案吗? 回答1 更新 我已经编写了一个更简单的版本,该版本也可以在IE <9中使用: https://stackoverflow.com/a/4812022/96100 旧答案 实际上,这是比整个文档文本中的字符偏移量更有用的结果:DOM范围的startOffset属性(即window.getSelection().getRangeAt()返回的内容)是相对于其startContainer属性的偏移量(顺便说一下,它不一定总是文本节点)。 但是,如果您确实想要字符偏移量,可以使用以下函数来实现。 这是一个实时示例:http://jsfiddle
  • 使用JS查找并替换文档中的特定文本字符(Find and replace specific text characters across a document with JS)
    问题 我想知道是否有一种轻量级的方法可以使用JavaScript或jQuery嗅探整个文档中的特定文本字符; 说出€并找到该字符的所有实例。 然后! 写一个能力,用$代替所有实例。 我找到了适合初学者的代码段: var str = 'test: ''; str = str.replace(/'/g, "'"); 本质上; 我想要一个一页文档的解决方案。 抓住X的所有实例,使其成为XY。 仅文字字符。 回答1 怎么样,用$代替@ : $("body").children().each(function () { $(this).html( $(this).html().replace(/@/g,"$") ); }); http://jsfiddle.net/maximua/jp96C/1/ 回答2 我自己的建议如下: function nativeSelector() { var elements = document.querySelectorAll("body, body *"); var results = []; var child; for(var i = 0; i < elements.length; i++) { child = elements[i].childNodes[0]; if(elements[i].hasChildNodes() && child
  • 突出显示搜索词(仅选择叶节点)(Highlight search terms (select only leaf nodes))
    问题 我想突出显示页面上的搜索词,但不要与任何HTML标记混淆。 我在想类似的东西: $('.searchResult *').each(function() { $(this.html($(this).html().replace(new RegExp('(term)', 'gi'), '<span class="highlight">$1</span>')); )}; 但是, $('.searchResult *').each匹配所有元素,而不仅仅是叶子节点。 换句话说,某些匹配的元素内部具有HTML。 所以我有几个问题: 如何仅匹配叶节点? 是否有一些内置的jQuery RegEx函数可以简化操作? 像这样的东西: $(this).wrap('term', $('<span />', { 'class': 'highlight' })) 有没有办法做一个简单的字符串替换而不是RegEx? 还有其他更好/更快的方法吗? 非常感谢! 回答1 [查看实际情况] // escape by Colin Snover // Note: if you don't care for (), you can remove it.. RegExp.escape = function(text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "
  • 如何更改页面上加载的HTML内容(How to change the HTML content as it's loading on the page)
    问题 我在我们的网站上进行A / B测试,我的大部分工作都放在一个JS文件中,该文件在呈现任何其他内容之前(但在jQuery加载后有时会派上用场)加载到页面顶部。 以更改H1标签的非常简单的示例为例,我通常会在头部注入一种样式,以将H1不透明度设置为0,然后在DOMContentLoaded上,我将操纵H1内容,然后将不透明度设置为1。是为了避免更改之前发生旧内容的闪烁-将整个对象隐藏起来更加美观。 我已经开始研究MutationObserver API。 在更改用户可以打开的覆盖对话框中的内容之前,我曾经使用过此方法,这似乎是一种很酷的方法,我想知道是否有人在第一次加载文档时设法使用MutationObserver来监听文档/在第一次呈现之前和DOMContentLoaded之前解析并更改文档? 然后,这种方法可以让我更改H1内容,而不必隐藏,更改和显示它。 到目前为止,我已经尝试过但失败了,最后只是阅读了有关即将过时的突变事件,并想知道我是否正在尝试做一些不可能的事情。 但是我们(不是我)设法在火星上放了一个机器人,所以我希望我能解决这个问题。 因此,可以在页面加载/解析时使用MutationObservers即时更改HTML内容吗? 感谢您的帮助或指点。 问候,尼克 回答1 MDN上的文档有一个通用的不完整示例,没有展示常见的陷阱。 突变摘要库提供了易于使用的包装器
  • 如何使用JavaScript访问CSS生成的内容(How to access CSS generated content with JavaScript)
    问题 我使用CSS的counter和content属性生成标题和图的编号: img.figure:after { counter-increment: figure; content: "Fig. " counter(section) "." counter(figure); } 这个(假定合适的浏览器)在任何图像之后都带有漂亮的标签“图1.1”,“图1.2”,依此类推。 问题:如何从Javascript访问此内容? 现在的问题是双重在于我想访问任一特定计数器的当前值(在某一DOM节点)或CSS生成的内容的值(在某一DOM节点)或,很明显,这两个信息。 背景:我想在链接后面附加指向数字的适当数字,如下所示: <a href="#fig1">see here</h> ------------------------^ " (Fig 1.1)" inserted via JS 据我所知,它可以归结为这个问题:我可以通过getComputedStyle访问content或counter-increment : var fig_content = window.getComputedStyle( document.getElementById('fig-a'), ':after').content; 但是,这不是活动值,而是在样式表中声明的值。 我找不到任何接口来访问真实的实时价值。
  • How to access CSS generated content with JavaScript
    I generate the numbering of my headers and figures with CSS's counter and content properties: img.figure:after { counter-increment: figure; content: "Fig. " counter(section) "." counter(figure); } This (appropriate browser assumed) gives a nice labelling "Fig. 1.1", "Fig. 1.2" and so on following any image. Question: How can I access this from Javascript? The question is twofold in that I'd like to access either the current value of a certain counter (at a certain DOM node) or the value of the CSS generated content (at a certain DOM node) or, obviously, both information. Background: I'd like
  • C#System.Windows.Automation获取元素文本(C# System.Windows.Automation get element text)
    问题 我正在尝试使用C#中的Automation从应用程序控件中获取文本/标签。 到目前为止,我可以使用此功能获取应用程序的AutomationElement树(例如记事本): private void WalkControlElements(AutomationElement rootElement, TreeNode treeNode) { AutomationElement elementNode = TreeWalker.ContentViewWalker.GetFirstChild(rootElement);; while (elementNode != null) { TreeNode childTreeNode = treeNode.Nodes.Add(elementNode.Current.ControlType.LocalizedControlType); // here I want to get text from 'elementNode' WalkControlElements(elementNode, childTreeNode); elementNode = TreeWalker.ControlViewWalker.GetNextSibling(elementNode); } } 我试图按照本文http://msdn.microsoft.com/zh
  • Swingworker with FileVisitor class and walkFileTree(), which iterates internally over a “set” of files in a directory tree; where to publish()?
    It seems like the long-running tree walker task should be defined in a class like so: public class TreeWalker extends SwingWorker<Void,String> implements FileVisitor<Path> And begun somewhere like so: TreeWalker walker = (new TreeWalker()); walker.execute(); The long-running task is not only initiated by but completely carried out by a single call to walkFileTree(), a method in the Files class. So surely the call to it has to be in doInBackGround(). protected Void doInBackground() throws Exception { Files.walkFileTree(SearchyGUI.p , this); return null; } Note that walkTreeFile() internally
  • 使用.text()仅检索未嵌套在子标记中的文本(Using .text() to retrieve only text not nested in child tags)
    问题 如果我有这样的html: <li id="listItem"> This is some text <span id="firstSpan">First span text</span> <span id="secondSpan">Second span text</span> </li> 我正在尝试使用.text()仅检索字符串“ This is some text”,但是如果我要说$('#list-item').text() ,则会得到“ This is some text”。 textSecond span text”。 有没有一种方法可以获取(并可能通过.text("")类的东西删除)标签中的自由文本,而不是其子标签中的文本? HTML不是我编写的,因此这是我必须使用的。 我知道在编写html时仅将文本包装在标签中会很简单,但是html是预先编写的。 回答1 我喜欢基于此处找到的clone()方法的可重用实现,以仅获取父元素内的文本。 提供的代码易于参考: $("#foo") .clone() //clone the element .children() //select all the children .remove() //remove all the children .end() //again go back to selected element
  • C# System.Windows.Automation get element text
    I am trying to get text/labels from application controls with Automation in C#. So far I am able to obtain AutomationElement tree of application (for example Notepad) with this function: private void WalkControlElements(AutomationElement rootElement, TreeNode treeNode) { AutomationElement elementNode = TreeWalker.ContentViewWalker.GetFirstChild(rootElement);; while (elementNode != null) { TreeNode childTreeNode = treeNode.Nodes.Add(elementNode.Current.ControlType.LocalizedControlType); // here I want to get text from 'elementNode' WalkControlElements(elementNode, childTreeNode); elementNode =