C# 使用XML名称空间时简化语法

C# 使用XML名称空间时简化语法,c#,.net,xml,vb.net,C#,.net,Xml,Vb.net,在一个简单的.vbproj文件中,如下所示: <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVe

在一个简单的.vbproj文件中,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    ...
  </PropertyGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
</Project>
我很确定应该存在一种更好的语法来简化上面的代码,可以只调用一次
XDocument.Elements()
,而不是
XDocument.Element()
,或者避免指定名称空间(或者多次调用mroe)但是,使用正确的XPath并使用
XDocument.XPathSelectElements()
似乎无法使用XPath v2.0忽略名称空间,如
/*:Project/PropertyGroup
(或者我的语法有误?)

有人可以解释我如何重构它


请注意,其目的是修改Xml的某些属性,然后将更改保存到文件中,而不仅仅是获取Xml中的数据(如果这对解决方案很重要)。

您可以将名称空间字符串放入变量中,并以这种方式使用它:

XNamespace yourns = "http://schemas.microsoft.com/developer/msbuild/2003";

IEnumerable<XElement> propGroups = 
    doc.Element(yourns + "Project").
        Elements(yourns + "PropertyGroup");
xns=”http://schemas.microsoft.com/developer/msbuild/2003";
IEnumerable propGroups=
文档元素(yourns+“项目”)。
元素(yourns+“PropertyGroup”);

我认为这是一个更具可读性和可重用性的解决方案。

您可以将名称空间字符串放入变量中,并以如下方式使用它:

XNamespace yourns = "http://schemas.microsoft.com/developer/msbuild/2003";

IEnumerable<XElement> propGroups = 
    doc.Element(yourns + "Project").
        Elements(yourns + "PropertyGroup");
xns=”http://schemas.microsoft.com/developer/msbuild/2003";
IEnumerable propGroups=
文档元素(yourns+“项目”)。
元素(yourns+“PropertyGroup”);

我认为这是一个更具可读性和可重用性的解决方案。

我最终发现了XPath v1.0的正确用法,这样完全避免了编写中间名称空间:

Dim propGroups As IEnumerable(Of XElement) =
    doc.XPathSelectElements("//*[local-name()='Project']//*[local-name()='PropertyGroup']")
但是,在大型层次结构的情况下,重复的字符串“
/*[local-name()=
”将导致与始终指定命名空间或多或少相同的注释语法。总之,我优先使用XPath,而不是LINQ to Objects查询

我不会接受我自己的答案,因为我不完全确定XPath语法是否尽可能简化


在XPath v2.0中也会简化很多,但是,似乎.NET不支持它(或者可能我在测试时使用了错误的语法)。

我最终发现了XPath v1.0的正确用法,这种方式完全避免了编写中间名称空间:

Dim propGroups As IEnumerable(Of XElement) =
    doc.XPathSelectElements("//*[local-name()='Project']//*[local-name()='PropertyGroup']")
但是,在大型层次结构的情况下,重复的字符串“
/*[local-name()=
”将导致与始终指定命名空间或多或少相同的注释语法。总之,我优先使用XPath,而不是LINQ to Objects查询

我不会接受我自己的答案,因为我不完全确定XPath语法是否尽可能简化


在XPathV2.0中也会简化很多,但是,似乎.NET不支持它(或者可能我在测试时使用了错误的语法)

XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
var propGroups = doc.Descendants(ns + "PropertyGroup");

API的目的是使用
+
运算符将名称空间与本地名称相结合,以避免在每个名称中包含名称空间的冗长。如果要标识使用名称空间的元素,则没有简单的方法可以避免使用名称空间。按本地名称进行筛选要比此详细得多。

如果您不参与如果您对明确确定
Project
PropertyGroup
的直接父级非常感兴趣,那么您可以使用
子体
查找所有
PropertyGroup
元素,无论它们出现在文档中的何处:

XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
var propGroups = doc.Descendants(ns + "PropertyGroup");

API的目的是使用
+
运算符将名称空间与本地名称相结合,以避免在每个名称中包含名称空间的冗长。如果要标识使用名称空间的元素,则没有简单的方法可以避免使用名称空间。按本地名称进行筛选比这更为冗长。

您看过吗?@Tim感谢您的参考,从我所看到的MSDN代码示例中显示的解决方案与我所做的相同,只是使用了一个变量来引用名称空间名称。老实说,我期待其他类型的正确解决方案,而不是MSDN所显示的解决方案。因为本质上,它显示的是相同的名称空间字符串,所有这些名称空间字符串都需要指定/连接时间。怎么样?它有本地名称的属性(没有名称空间),以及相关XNamespace的名称空间和URI。我通常使用:IEnumerable propGroups=doc.subjects()。其中(x=>x.name.LocalName==“PropertyGroup”);你看了吗?@Tim谢谢你的参考,从我看到的MSDN代码示例中显示的解决方案与我做的相同,只是使用了一个变量来引用名称空间名称。老实说,我期待其他类型的正确解决方案,而不是MSDN显示的解决方案。因为本质上它显示的是相同的,需要指定的名称空间字符串ied/一直在连接。怎么样?它有本地名称的属性(没有名称空间),以及相关XNamespace的名称空间和URI。我通常使用:IEnumerable propGroups=doc.subjects()。其中(x=>x.name.LocalName==“PropertyGroup”);感谢您的回答,但是您给出的示例中仍然存在两次指定名称空间的需要,就像我提供的原始代码中一样,只是方式有所不同。老实说,在发布问题中的代码时,我忽略了将字符串放入变量的事实,但我希望其他类型的解决方案并不意味着这样做。您应该从名称空间中删除
{}
,因为这不是名称空间的一部分。你是对的!我做了一个错误的复制和粘贴。很抱歉,我编辑了答案。谢谢@CharlesMager。谢谢你的答案,但是在你给出的示例中仍然需要指定两次名称空间,就像我提供的原始代码一样,