繁体   English   中英

使用xmlns属性(命名空间)查询XDocument

[英]Query XDocument with xmlns attribute (namespace)

我尝试从visual studio * .csproj文件中查询元素。 我创建了一个简短的例子来说明问题:

    // Working
    string xml1 = @"<Project ToolsVersion='4.0'>
                      <ItemGroup Label='Usings'>
                        <Reference Include='System' />
                        <Reference Include='System.Xml' />
                      </ItemGroup>
                    </Project>"; 
    // Not working
    string xml2 = @"<Project ToolsVersion='4.0' xmlns='http://schemas.microsoft.com/developer/msbuild/2003'>
                      <ItemGroup Label='Usings'>
                        <Reference Include='System' />
                        <Reference Include='System.Xml' />
                      </ItemGroup>
                    </Project>";

    XDocument doc = XDocument.Parse(xml2);

    foreach (XElement element in doc.Descendants("ItemGroup"))
    {
        Console.WriteLine(element);
    }

字符串xml1工作正常,xml2不返回任何内容。 这些字符串之间的唯一区别是文档根目录中的xmlns属性。

我如何查询包含xmlns属性的文档? 当xml文档包含xmlns属性时,为什么会出现问题?

当xml文档包含xmlns属性时,为什么会出现问题?

它不是,如果你理解它的含义:)基本上你已经将“ http://schemas.microsoft.com/developer/msbuild/2003 ”的默认命名空间URI应用于所有元素。 因此,在查询时,您还需要指定该命名空间。 幸运的是,LINQ to XML使这非常简单:

XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
XDocument doc = XDocument.Parse(xml2);
foreach (XElement element in doc.Descendants(ns + "ItemGroup"))
{
    Console.WriteLine(element);
}

事先没有必要知道命名空间。 您可以编写适用于两个Xml的代码,因为您可以从XElement获取默认命名空间。

XDocument doc = XDocument.Parse(xml2);
XNamespace ns = doc.Root.GetDefaultNamespace();
foreach (XElement element in doc.Descendants(ns + "ItemGroup"))
{
    Console.WriteLine(element);
}

我还编写了一个扩展方法来解析任何XObject(XElement,XDocument等)中的XName。

使用扩展方法而不是GetDefaultNamespace的好处是您不必检查是否已经提供了另一个命名空间。

public static XName ResolveName(this XObject xObj, XName name)
{
    //If no namespace has been added, use default namespace anyway
    if (string.IsNullOrEmpty(name.NamespaceName))
    {
        name = xObj.Document.Root.GetDefaultNamespace() + name.LocalName;
    }
    return name;
}

你可以像这样使用它

XDocument doc = XDocument.Parse(xml2);
foreach (XElement element in doc.Descendants(doc.ResolveName("ItemGroup")))
{
    Console.WriteLine(element);
}

我认为LINQ to XML是一个很棒的API。 但我认为很明显,如果我不提供命名空间,我总是指默认命名空间。 我没有看到任何理由为什么LINQ to XML不会以这种方式运行。 这有点让我恼火的缺点。 第一次作为LINQ to XML的初学者,当我忘记提供默认命名空间时,我几个小时都不知道我做错了什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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