title: Using XPath and WebBrowser Control to select multiple nodes
body: <p>In C# WinForms sample application I have used WebBrowser control and <a href="http://coderepos.org/share/wiki/JavaScript-XPath" rel="nofollow noreferrer" title="JavaScript-XPath">JavaScript-XPath</a> to select single node and change that node .innerHtml by the following code:</p>
  
  <pre><code>    private void MainForm_Load(object sender, EventArgs e)
      {
          webBrowser1.DocumentText = @"
              &lt;html&gt;
              &lt;head&gt;
                  &lt;script src=""http://svn.coderepos.org/share/lang/javascript/javascript-xpath/trunk/release/javascript-xpath-latest-cmp.js""&gt;&lt;/script&gt;
              &lt;/head&gt;
              &lt;body&gt;
              &lt;img alt=""0764547763 Product Details"" 
                  src=""http://ecx.images-amazon.com/images/I/51AK1MRIi7L._AA160_.jpg""&gt;
              &lt;hr/&gt;
              &lt;h2&gt;Product Details&lt;/h2&gt;
              &lt;ul&gt;
              &lt;li&gt;&lt;b&gt;Paperback:&lt;/b&gt; 648 pages&lt;/li&gt;
              &lt;li&gt;&lt;b&gt;Publisher:&lt;/b&gt; Wiley; Unlimited Edition edition (October 15, 2001)&lt;/li&gt;
              &lt;li&gt;&lt;b&gt;Language:&lt;/b&gt; English&lt;/li&gt;
              &lt;li&gt;&lt;b&gt;ISBN-10:&lt;/b&gt; 0764547763&lt;/li&gt;
              &lt;/ul&gt;
              &lt;/body&gt;
              &lt;/html&gt;
          ";
      }
  
      private void cmdTest_Click(object sender, EventArgs e)
      {
          string xPath = "//li";
          string code = string.Format("document.evaluate('{0}', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;", xPath);
          var li = webBrowser1.Document.InvokeScript("eval", new object[] { code }) as mshtml.IHTMLElement;
  
          li.innerHTML = string.Format("&lt;span style='text-transform: uppercase;font-family:verdana;color:green;'&gt;{0}&lt;/span&gt;", li.innerText);
  
      }
  </code></pre>
  
  <p>The result of running this code is as the following:</p>
  
  <p><img src="https://i.stack.imgur.com/eDJ1s.png" alt="Sample code execution result"></p>
  
  <p>Now I'd like to use the same technique to select multiple <code>&lt;li&gt;</code>nodes under <code>&lt;ul&gt;</code> node and I'm writing:</p>
  
  <pre><code>        xPath = "//ul//*";
          code = string.Format("document.evaluate('{0}', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);", xPath);
          var allLI = webBrowser1.Document.InvokeScript("eval", new object[] { code }) as mshtml.IHTMLElementCollection;
  </code></pre>
  
  <p>but the returned value of <code>allLI</code> variable is <code>NULL</code> .</p>
  
  <p>If I'll write</p>
  
  <pre><code>        xPath = "//ul//*";
          code = string.Format("document.evaluate('{0}', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);", xPath);
          var allLI = webBrowser1.Document.InvokeScript("eval", new object[] { code }); 
  </code></pre>
  
  <p>then the returned <code>allLI</code> variable isn't null and its value type is <code>COM Object</code> but what more specific type this <code>COM Object</code> can be cast to is unclear for me.</p>
  
  <p>Is there a way to select multiple nodes by used here technique?</p>
  
  <p><strong>[EDITED]</strong></p>
  
  <p>xPath = "ul//*";</p>
  
  <p>to</p>
  
  <p>xPath = "//ul//*";</p>
  
  <p><strong>[Addition]</strong></p>
  
  <p>I have added two javaScript functions to my sample HTML:</p>
  
  <pre><code>&lt;script type=""text/javascript""&gt;
      function GetElementsText (XPath) {
              var xPathRes = document.evaluate ( XPath, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);              
              var nextElement = xPathRes.iterateNext ();
              var text = """";
              while (nextElement) {
                 text += nextElement.innerText;
                 nextElement = xPathRes.iterateNext ();
              }
          return text;
          };
  
      function GetElements (XPath) {
              var xPathRes = document.evaluate ( XPath, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);              
              var nextElement = xPathRes.iterateNext ();
              var elements = new Object();
              var elementIndex = 1;
              while (nextElement) {
                 elements[elementIndex++] = nextElement;
                 nextElement = xPathRes.iterateNext ();
              }
          return elements;
          };
  &lt;/script&gt;
  </code></pre>
  
  <p>Now when I'm runnung the following C# code line within my <code>cmd_TestClick</code> method:</p>
  
  <pre><code>var text = webBrowser1.Document.InvokeScript("eval", new object[] { "GetElementsText('//ul')" });
  </code></pre>
  
  <p>I'm getting text of all <code>li</code> elements:</p>
  
  <pre><code>"Paperback: 648 pages \r\nPublisher: Wiley; Unlimited Edition edition (October 15, 2001) \r\nLanguage: English \r\nISBN-10: 0764547763 "
  </code></pre>
  
  <p>And when I'm running the following C# code line within my <code>cmd_TestClick</code> method:</p>
  
  <pre><code>var elements = webBrowser1.Document.InvokeScript("eval", new object[] { "GetElements('//ul')" });
  </code></pre>
  
  <p>I'm getting <code>COM Object</code>, which I cannot cast to <code>IEnumerable&lt;mshtml.IHtmlElement&gt;</code> .</p>
  
  <p>Is there any way to process within C# code a javaScript collection of HTML nodes returned by</p>
  
  <pre><code>var elements = webBrowser1.Document.InvokeScript("eval", new object[] { "GetElements('//ul')" });
  </code></pre>
  
  <p>?</p>