使用XElement查询带有命名空间的节点。

9

我正在尝试从一个类似于这样的csproj文件中提取一个节点,但是无法成功——可能是因为命名空间声明的原因。

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
      <PropertyGroup>
          <RegisterForComInterop>true</RegisterForComInterop>

这个会彻底失败:

XDocument cpo = XDocument.Load(file);
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/200");
IEnumerable<XElement> list3 = cpo.XPathSelectElements("//x:RegisterForComInterop[.='true']", nsm);

有没有人有任何想法?

谢谢。

1个回答

18

你真的想使用XPath来完成这个任务吗?在LINQ to XML中使用命名空间非常容易:

XDocument cpo = XDocument.Load(file);
XNamespace x = "http://schemas.microsoft.com/developer/msbuild/2003";
var elements = cpo.Descendants(x + "RegisterForComInterop")
                  .Where(x => (string) x == "true");

或者,如果您绝对确信每个RegisterForComInterop都有一个合适的布尔值,您可以使用显式XElementbool转换:

XDocument cpo = XDocument.Load(file);
XNamespace x = "http://schemas.microsoft.com/developer/msbuild/2003";
var elements = cpo.Descendants(x + "RegisterForComInterop")
                  .Where(x => (bool) x);

个人而言,如果涉及到命名空间,我通常会选择这种方法而不是XPath,尤其是


我会用 .Where(x => bool.Parse(x.Value)) 替换最后一行,因为我们百分之百期望一个布尔字符串(否则我们期望抛出异常..)。 - Shimmy Weitzhandler
@Shimmy:我不会在这里使用bool.Parse - 我会使用显式转换为bool,它知道XML。我会修改一下。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接