使用XPathEvaluate在Linq-to-Xml查询中获取文本节点值

Gre*_*ray 2 c# xpath linq-to-xml

我最近遇到过一种情况,我必须使用XPath作为Linq to XML查询的一部分,并发现它有点奇怪.我确信还有其他方法可以使用本机XElement API方法解决问题,但在这种情况下,XPath更适合定位我需要的特定XML文本值,因为文档结构非常复杂.我最终找到了一种让它工作的方法(见下文),但它不是很漂亮,这通常意味着我错过了一些东西.

我的问题是如何使用XPathEvalute或其他一些XPath方法返回一个字符串值,该值可以在where语句中使用,也可以作为select方法中新对象的一部分使用.我找到了一个在LINQ中使用大量转换和Null合并运算符的解决方案,但必须有一个更清洁的方法.问题的根源是XPathEvaluate方法通常会返回一个XText元素(转换为通用对象),但Linq将其转换为IEnumerable,以便它可以延迟执行.当您尝试访问该对象的值时,这会导致问题,因为在执行查询之前它不会实现.

下面是示例:使用以下XML文档查找具有相同名称的Boy and Girl的所有父项.这必须使用XPath查询来完成,因为在我的情况下,文档结构很复杂.

//Use C# Program Language type in LinqPad
void Main()
{
    var xml = XElement.Parse(@"<Root>
        <Parent>
            <Boy>Anne</Boy>
        </Parent>
        <Parent>
            <Boy>Alex</Boy>
            <Girl>Alex</Girl>
        </Parent>
        <Parent>
            <Boy>Jay</Boy>
        </Parent>
    </Root>");

    var q1 = from e in xml.XPathSelectElements("/Parent")
             select e;

    q1.Dump();

    var q2 = from e in q1
             let boy = ((IEnumerable<Object>)e.XPathEvaluate("Boy/text()")).Cast<System.Xml.Linq.XText>().FirstOrDefault() ?? new System.Xml.Linq.XText("")
             let girl = ((IEnumerable<Object>)e.XPathEvaluate("Girl/text()")).Cast<System.Xml.Linq.XText>().FirstOrDefault() ?? new System.Xml.Linq.XText("")
             select new {t=boy.GetType(), b=boy, g=girl, same=(boy.Value==girl.Value)};

    q2.Dump();
}
Run Code Online (Sandbox Code Playgroud)

结果是:

在此输入图像描述

您可以看到第二个元素被识别为具有相同名称的男孩和女孩.有没有更简洁的方法在仍然使用XPath时这样做,或者我坚持使用上面的代码.

Mic*_*Liu 5

是否可以使用XPathSelectElement而不是XPathEvaluate

var q2 = from e in q1
         let boy = (string)e.XPathSelectElement("Boy")
         let girl = (string)e.XPathSelectElement("Girl")
         where boy.StartsWith("A") //Optional use in where statement
         select new { t = boy.GetType(), b = boy, g = girl, same = (boy == girl) };
Run Code Online (Sandbox Code Playgroud)

  • `XElement`强制转换操作符非常方便. (2认同)