【问题标题】:LINQ to XML calling .Value returns null objectLINQ to XML 调用 .Value 返回空对象
【发布时间】:2023-03-17 06:29:01
【问题描述】:

在更改 .csproj 文件中的设置的程序中,以下 linq to xml 语句始终返回“对象未设置为对象的实例”:

static void Main(string[] args)
    {
        string rootDir =
            @"e:\path\to\proj\file\foo.csproj";

        var xDoc = XDocument.Load(rootDir);
        var ns = xDoc.Root.Name.Namespace;

        var hasConditions = xDoc.Root.Elements(ns + "PropertyGroup")
            .Where(x => x.Attribute("Condition") != null);

        Console.WriteLine(hasConditions.Count());

        try
        {
            var debugConfig = xDoc.Root.Elements(ns + "PropertyGroup")
                .Where(x => x.Attribute("Condition")
                .Value == " '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ");

            Console.WriteLine(debugConfig.Count());
        }
        catch
        {
            Console.WriteLine("doesn't work");
        }
    }

完整的项目文件:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{F08E2AEB-A1C2-43F9-A93C-38AF2A99C96A}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>CommunicationSystem.XmlLoading.Common</RootNamespace>
    <AssemblyName>CommunicationSystem.XmlLoading.Common</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <SccProjectName>SAK</SccProjectName>
    <SccLocalPath>SAK</SccLocalPath>
    <SccAuxPath>SAK</SccAuxPath>
    <SccProvider>SAK</SccProvider>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <RunCodeAnalysis>true</RunCodeAnalysis>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <RunCodeAnalysis>true</RunCodeAnalysis>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'DEV|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\DEV\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'SIT|AnyCPU'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>bin\SIT\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <DebugType>full</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'QA|AnyCPU'">
    <OutputPath>bin\QA\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <Optimize>true</Optimize>
    <DebugType>pdbonly</DebugType>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <ErrorReport>prompt</ErrorReport>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="StorageSystem">
      <HintPath>..\..\..\GlobalDependencies\StorageSystem\beta\StorageSystem.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Core" />
    <Reference Include="System.Web" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Common\IEnumerableExtensions.cs" />
    <Compile Include="Common\XmlLoaderBase.cs" />
    <Compile Include="Configuration\SchemasConfigurationElement.cs" />
    <Compile Include="Configuration\SettingsConfigurationElement.cs" />
    <Compile Include="Configuration\TConfigurationElementCollection.cs" />
    <Compile Include="Configuration\XmlLoadingConfigurationSection.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Validation\XValidationResult.cs" />
    <Compile Include="Validation\XValidator.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
   Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>

我的怀疑是它与属性值中的空格有关,但我不能确定....还有其他人面临类似的情况吗?

【问题讨论】:

    标签: c# .net xml linq linq-to-xml


    【解决方案1】:

    我怀疑这是问题所在:

    x.Attribute(ns + "Condition")
    

    确定该属性在命名空间中吗? (与元素名称不同,属性名称不会从 xmlns="..." 继承“默认”命名空间。)尝试一下:

    x.Attribute("Condition")
    

    编辑:如果问题确实是 all 元素上不存在该属性,那么解决方案比arcain 提出的解决方案更简单。您可以使用强制转换为字符串:

    var debugConfig = xDoc.Root.Elements(ns + "PropertyGroup").Where(x => 
          (string) x.Attribute("Condition") == " [long string here] ");
    

    字符串转换将在 null 上调用时返回 null,这是您想要的。

    (对混乱的格式表示歉意 - SO 上的短线使它变得棘手。)

    【讨论】:

    • 删除命名空间后问题依然存在
    • @ErOx:如果你能展示一个简短但完整的程序,包括一个简短但完整的输入 XML 示例,那将会很有帮助。否则我们真的会猜测。
    • 哇,因为没有早点意识到这一点而自责。这么简单,喜欢。谢谢
    • @JonSkeet 很好的简化,但如果属性值中有前导或尾随空格,那么您的解决方案将找不到这些元素。这就是我使用IndexOf 的原因。我的项目文件的Condition 属性值和上面的 ErOx 有一些带有额外空格的属性。
    • @arcain:当然——我正在讨论这个特定问题的要求。不过,对于更复杂的要求,我可能会使用 let 子句 - 它使它更简单一些。
    【解决方案2】:

    我不得不执行类似的任务,但遇到了同样的问题。根本原因是Condition 属性可能并不存在于所有PropertyGroup 元素上。这是来自我的LINQPad 脚本的查询(这是 .Dump() 方法的来源。)

    string projFile = @"FileName";
    
    XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
    XDocument doc = XDocument.Load(projFile);
    
    var query = from node in doc.Root.Descendants(ns + "PropertyGroup")
            where node.Attribute("Condition") != null // this fixed the issue
            && node.Attribute("Condition").Value.IndexOf(
                    "'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'",
                    StringComparison.OrdinalIgnoreCase) >= 0
            select node;
    
    query.Dump();
    

    【讨论】:

    • 啊是的,解决了它。谢谢!顺便说一句,我也在为此使用 linqpad(不重要,但我非常喜欢它,我只需要分享它)
    • @ErOx:请参阅我的答案,了解更简单的做法。
    • @ErOx 我在 LINQPad 中 live;很高兴为您提供帮助。
    【解决方案3】:

    您已经有了答案,但我使用 this xml library 和这个简单的 XPath 解决了它:

    XElement root = XElement.Load(file);
    XElement node = root.XPathElement("//PropertyGroup[@Condition={0}]",
                    " '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ");
    

    【讨论】:

      猜你喜欢
      • 2011-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多