简体   繁体   中英

Xpath expression to LINQ expression

I have rewrote this XPath expression to linq, but something is wrong (no element found exception). My Html:

string xml = @"
<root>
   <div id=""main"">
      <div class=""content"">
         <ul>
            something
         </ul>
      </div>
      <div class=""content"">
         <ul>
            something
         </ul>
      </div>
      <div class=""content"">
         <ul>
            <li>
               <div>My text</div>
            </li>
         </ul>
      </div>
   </div>
</root>
";

Xpath:

//div[@id="main"]//div[@class="content"]/ul/li/div

LINQ:

string Content =
            doc.DocumentNode.Descendants("div").First(x => x.GetAttributeValue("id", null) == "main")
                .Descendants("div").First(x => x.GetAttributeValue("class", null) == "content")
                .Descendants("ul").First()
                .Descendants("li").First()
                .Descendants("div").First().InnerText

background: I have to use LINQ, because I am using Portable library.

I have already solved my problem with slightly different expression:

string Content =
            doc.DocumentNode.Descendants("div").First(x => x.GetAttributeValue("id", null) == "main")
                .Descendants("div").Where(x => x.GetAttributeValue("class", null) == "content").ElementAt(2)
                .Descendants("ul").First()
                .Descendants("li").First()
                .Descendants("div").First().InnerText;

It works, but it is not same as Xpath.

So I am asking you: Does exist LINQ expression, which finds Node with InnerText without specifying exact location (like Xpath)?

I think this is what you want... you are expecting the first match in the document and not all matches right?

string Content =
    doc.DocumentNode.Descendants("div").Where(x => x.GetAttributeValue("id", null) == "main")
        .Descendants("div").Where(x => x.GetAttributeValue("class", null) == "content")
        .Elements("ul")
        .Elements("li")
        .Elements("div").First().Value;

In general...

XPath '//' -> translates to LINQ .Descendants

XPath '/' -> translates to LINQ .Elements

This code will retrieve the InnerText of your target div:

var doc = new HtmlDocument();

string xml = @"<root>
                  <div id=""main"">
                    <div class=""content"">
                        <ul>
                            <li>
                                <div>Test</div>
                            </li>
                        <ul>
                    </div>
                  </div>
                </root>";

var bytes = System.Text.Encoding.UTF8.GetBytes(xml);
var memStream = new MemoryStream(bytes);

doc.Load(memStream);

var innerText =
doc.DocumentNode.Descendants("div").Where(x => x.GetAttributeValue("id", null) == "main").First()
.Descendants("div").Where(x => x.GetAttributeValue("class", null) == "content").First()
.Elements("ul").First()
.Elements("li").First()
.Elements("div").First().InnerText;

When this is run "innerText" is equal to "Test" (ie the innerText of the div)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM