Powershell/C# XmlDocument 只选择没有属性的节点

Posted

技术标签:

【中文标题】Powershell/C# XmlDocument 只选择没有属性的节点【英文标题】:Powershell/C# XmlDocument selecting only the nodes without attributes 【发布时间】:2020-05-30 17:47:33 【问题描述】:

我正在尝试读取 Visual Studio 项目文件以选择没有属性的 <PropertyGroup> 项以从 <AssemblyName> 节点中提取值。 post 接近我正在寻找的东西,但我需要它没有属性而不是没有特定属性

我在 Powershell 中尝试了以下操作,但没有成功。

$xml = [System.Xml.XmlDocument]::new();

$xml.Load("WebApplication4.csproj")
$ns = [System.Xml.XmlNamespaceManager]::new($xml.NameTable);
$ns.AddNamespace("prj", "http://schemas.microsoft.com/developer/msbuild/2003")

$xml.SelectNodes("//prj:PropertyGroup", $ns).Count

有没有办法在selectsinglenode 方法中使用xpath 语法,只返回一个没有属性的节点?

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props" Condition="Exists('..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.7\build\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.props')" />
  <Import Project="..\packages\Microsoft.Net.Compilers.2.1.0\build\Microsoft.Net.Compilers.props" Condition="Exists('..\packages\Microsoft.Net.Compilers.2.1.0\build\Microsoft.Net.Compilers.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>
    </ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>7EC4A73B-EA1B-4A6C-B2ED-093E3615C40E</ProjectGuid>
    <ProjectTypeGuids>349c5851-65df-11da-9384-00065b846f21;fae04ec0-301f-11d3-bf4b-00c04f79efbc</ProjectTypeGuids>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>WebApplication4</RootNamespace>
    <AssemblyName>WebApplication4</AssemblyName>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <UseIISExpress>true</UseIISExpress>
    <Use64BitIISExpress />
    <IISExpressSSLPort />
    <IISExpressAnonymousAuthentication />
    <IISExpressWindowsAuthentication />
    <IISExpressUseClassicPipelineMode />
    <UseGlobalApplicationHostFile />
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
</Project>

【问题讨论】:

【参考方案1】:

仅使用 xpath 的另一种方法可能是:

 $xml.SelectNodes("//prj:PropertyGroup[count(@*)=0]", $ns)

【讨论】:

【参考方案2】:

Jack Fleeting's helpful answer 展示了如何仅使用 XPath 正确地完成它。

以下替代方法显示了如何在 PowerShell 代码中执行事后过滤。


您需要检查目标元素上.Attributes 集合的长度以找到没有属性的集合:

$xml.SelectNodes("//prj:PropertyGroup", $ns).Where( $_.Attributes.Count -eq 0 )

请注意,.Where() 是 PowerShell 提供的数组(集合)方法,可以通过脚本块 ( ... ) 过滤任何集合,该脚本块需要为每个元素 ($_) 返回 $true已选中。

【讨论】:

以上是关于Powershell/C# XmlDocument 只选择没有属性的节点的主要内容,如果未能解决你的问题,请参考以下文章

将 XDocument 转换为 XmlDocument,反之亦然

.NET XmlDocument LoadXML 和实体

为啥`XmlDocument.LoadXml()`不适用于命名空间?

从 XmlDocument 中删除节点

如何在 XmlDocument 中插入/替换 XML 标签?

XmlDocument.Load 多个根元素