rism
rism

Reputation: 12142

How to use XDocument to read csproj files?

I wanted to make some path changes to csproj files to configure for source control. Rather than do it by hand I figured Id iterate over the csproj files and use Linq-to-Xml within each csproj to alter the build and reference paths according to need.

So Ive looked around and am presently trying to use:

public void Read(string  fileName)
{
    XDocument doc = XDocument.Load(fileName);

    foreach (XElement el in doc.Root.Elements())
    {
        Console.WriteLine("{0} {1}", el.Name, el.Attribute("id").Value);
        Console.WriteLine("  Attributes:");
        foreach (XAttribute attr in el.Attributes())
            Console.WriteLine("    {0}", attr);
        Console.WriteLine("  Elements:");

        foreach (XElement element in el.Elements())
            Console.WriteLine("    {0}: {1}", element.Name, element.Value);
    }
}

as per accepted answer of this SO question xml-parsing-read-a-simple-xml-file-and-retrieve-values. However when the line

foreach (XElement el in doc.Root.Elements())

is processed I get a null reference error on the call to Elements. I've also tried calling Nodes, Descendants, etc but they are all null. doc. doc.Root does return everything in the proj file (except the namespace line at the top), so there is something there I'm just not walking it properly.

So what am I doing wrong? I expected Elements to return a collection of XML fragment I could walk or filter to pull out the pieces I want i.e.

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

Update:

So this is a csproj example:

<?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>{2CCAB46D-7A7C-4C65-B6D2-DC2D4049FCD9}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Basd.Core</RootNamespace>
    <AssemblyName>Basd.Core</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <TargetFrameworkProfile>
    </TargetFrameworkProfile>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>..\..\Basd.Bin\AnyCPU\Release\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>..\..\Basd.Bin\AnyCPU\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <PlatformTarget>AnyCPU</PlatformTarget>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
    <PlatformTarget>x86</PlatformTarget>
    <OutputPath>..\..\Basd.Bin\x86\Debug\</OutputPath>
    <DebugType>full</DebugType>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <OutputPath>..\..\Basd.Bin\AnyCPU\Release\</OutputPath>
    <DefineConstants>
    </DefineConstants>
    <DebugType>pdbonly</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <Prefer32Bit>false</Prefer32Bit>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Microsoft.VisualBasic" />
    <Reference Include="System" />
    <Reference Include="System.Configuration" />
    <Reference Include="System.Core" />
    <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="Activation\ActivationExtensions.cs" />
    <Compile Include="Activation\ActivationMetaDataList.cs" />
    <Compile Include="Activation\ActivationProviderFactory.cs" />
    <Compile Include="Activation\ActivationMetaDataConfigurationProvider.cs" />
    <Compile Include="Activation\ActivationMetaDataConfigurationProviderSection.cs" />
    <Compile Include="Activation\ActivationMetaDataProvider.cs" />
    <Compile Include="Activation\IActivationMetaData.cs" />
    <Compile Include="Activation\ActivationMetaData.cs" />
    <Compile Include="Activation\IActivationMetaDataProvider.cs" />
    <Compile Include="Collections\DomainList.cs" />
    <Compile Include="DateTime\GenerationDateRange.cs" />
    <Compile Include="DateTime\DateBlitterExtensions.cs" />
    <Compile Include="Dto\DTOStub.generic.cs" />
    <Compile Include="Dto\Tabulation.cs" />
    <Compile Include="Dto\TabulatedItem.cs" />
    <Compile Include="Dto\DTOStub.cs" />
    <Compile Include="Environment\EnvironmentContext.cs" />
    <Compile Include="Events\Delegates.cs" />
    <Compile Include="Activation\ActivationHelper.cs" />
    <Compile Include="Helpers\ObjectScrubber.cs" />
    <Compile Include="Helpers\SmtpHelper.cs" />
    <Compile Include="Interfaces\INameHolder.cs" />
    <Compile Include="Interfaces\IFrame.cs" />
    <Compile Include="Events\FrameEventArgs.cs" />
    <Compile Include="Events\PayloadedEventArgs.cs" />
    <Compile Include="Helpers\DateHelper.cs" />
    <Compile Include="Helpers\EnumerableDataSources.cs" />
    <Compile Include="Helpers\EnumHelper.cs" />
    <Compile Include="Helpers\StringsHelper.cs" />
    <Compile Include="Interfaces\IIndexable.cs" />
    <Compile Include="Interfaces\INameable.cs" />
    <Compile Include="Collections\NamedList.cs" />
    <Compile Include="Interfaces\IText.cs" />
    <Compile Include="Events\KeyChangedEventArgs.cs" />
    <Compile Include="DateTime\DateRange.cs" />
    <Compile Include="DateTime\EntityDateRange.cs">
      <SubType>Code</SubType>
    </Compile>
    <Compile Include="DateTime\IMinimumBoundedDateRange.cs" />
    <Compile Include="DateTime\IDateRange.cs" />
    <Compile Include="Enumerations.cs" />
    <Compile Include="DateTime\IEntityDateRange.cs" />
    <Compile Include="Interfaces\IUserNotifier.cs" />
    <Compile Include="Collections\IXtendedEnumerable.cs" />
    <Compile Include="Membership.cs" />
    <Compile Include="DateTime\MinimumBoundedDateRange.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="Properties\Resources.Designer.cs">
      <AutoGen>True</AutoGen>
      <DesignTime>True</DesignTime>
      <DependentUpon>Resources.resx</DependentUpon>
    </Compile>
    <Compile Include="SeriesCube.cs" />
    <Compile Include="Collections\XList.cs" />
  </ItemGroup>
  <ItemGroup>
    <Folder Include="Compression\" />
  </ItemGroup>
  <ItemGroup>
    <EmbeddedResource Include="Properties\Resources.resx">
      <Generator>ResXFileCodeGenerator</Generator>
      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
    </EmbeddedResource>
  </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>

From Intermediate Window with breakpoint set on

 foreach (XElement el in doc.Root.Elements())

?doc.Root.ToString(); "<Project ToolsVersion=\"4.0\" DefaultTargets=\"Build\" xmlns=\"http://schemas.microsoft.com/developer/msbuild/2003\">\r\n  <PropertyGroup>\r\n    <Configuration Condition=\" '$(Configuration)'
== '' \">Debug</Configuration>\r\n    <Platform Condition=\" '$(Platform)' == '' \">AnyCPU</Platform>\r\n    <ProductVersion>8.0.30703</ProductVersion>\r\n    <SchemaVersion>2.0</SchemaVersion>\r\n    <ProjectGuid>{2CCAB46D-7A7C-4C65-B6D2-DC2D4049FCD9}</ProjectGuid>\r\n  <OutputType>Library</OutputType>\r\n    <AppDesignerFolder>Properties</AppDesignerFolder>\r\n    <RootNamespace>Basd.Core</RootNamespace>\r\n    <AssemblyName>Basd.Core</AssemblyName>\r\n    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>\r\n    <FileAlignment>512</FileAlignment>\r\n    <TargetFrameworkProfile></TargetFrameworkProfile>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' \">\r\n    <DebugSymbols>true</DebugSymbols>\r\n    <DebugType>full</DebugType>\r\n    <Optimize>false</Optim ize>\r\n    <OutputPath>..\\..\\Basd.Bin\\AnyCPU\\Release\\</OutputPath>\r\n    <DefineConstants>DEBUG;TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <Prefer32Bit>false</Prefer32Bit>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">\r\n    <DebugType>pdbonly</DebugType>\r\n    <Optimize>true</Optimize>\r\n    <OutputPath>..\\..\\Basd.Bin\\AnyCPU\\Release\\</OutputPath>\r\n    <DefineConstants>TRACE</DefineConstants>\r\n    <ErrorReport>prompt</ErrorReport>\r\n    <WarningLevel>4</WarningLevel>\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <Prefer32Bit>false</Prefer32Bit>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Debug|x86'\">\r\n    <PlatformTarget>x86</PlatformTarget>\r\n    <OutputPath>..\\..\\Basd.Bin\\x86\\Debug\\</OutputPath>\r\n    <DebugType>full</DebugType>\r\n    <Prefer32Bit>fals e</Prefer32Bit>\r\n  </PropertyGroup>\r\n  <PropertyGroup Condition=\"'$(Configuration)|$(Platform)' == 'Release|x86'\">\r\n    <PlatformTarget>AnyCPU</PlatformTarget>\r\n    <OutputPath>..\\..\\Basd.Bin\\AnyCPU\\Release\\</OutputPath>\r\n    <DefineConstants></DefineConstants>\r\n    <DebugType>pdbonly</DebugType>\r\n    <DebugSymbols>true</DebugSymbols>\r\n    <Prefer32Bit>false</Prefer32Bit>\r\n  </PropertyGroup>\r\n  <ItemGroup>\r\n    <Reference Include=\"Microsoft.VisualBasic\" />\r\n <Reference Include=\"System\" />\r\n    <Reference Include=\"System.Configuration\" />\r\n    <Reference Include=\"System.Core\" />\r\n    <Reference Include=\"System.Xml.Linq\" />\r\n    <Reference Include=\"System.Data.DataSetExtensions\" />\r\n    <Reference Include=\"Microsoft.CSharp\" />\r\n    <Reference Include=\"System.Data\" />\r\n    <Reference Include=\"System.Xml\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Compile Include=\"Activation\\ActivationExtensions.cs\" />\r\n    <Compile Include=\"Activation\\Act ivationMetaDataList.cs\" />\r\n    <Compile Include=\"Activation\\ActivationProviderFactory.cs\" />\r\n    <Compile Include=\"Activation\\ActivationMetaDataConfigurationProvider.cs\" />\r\n    <Compile Include=\"Activation\\ActivationMetaDataConfigurationProviderSection.cs\" />\r\n    <Compile Include=\"Activation\\ActivationMetaDataProvider.cs\" />\r\n    <Compile Include=\"Activation\\IActivationMetaData.cs\" />\r\n    <Compile Include=\"Activation\\ActivationMetaData.cs\" />\r\n    <Compile Include=\"Activation\\IActivationMetaDataProvider.cs\" />\r\n <Compile Include=\"Collections\\DomainList.cs\" />\r\n    <Compile Include=\"DateTime\\GenerationDateRange.cs\" />\r\n    <Compile Include=\"DateTime\\DateBlitterExtensions.cs\" />\r\n    <Compile Include=\"Dto\\DTOStub.generic.cs\" />\r\n    <Compile Include=\"Dto\\Tabulation.cs\" />\r\n    <Compile Include=\"Dto\\TabulatedItem.cs\" />\r\n    <Compile Include=\"Dto\\DTOStub.cs\" />\r\n    <Compile Include=\"Environment\\EnvironmentContext.cs\" />\r\n    <C ompile Include=\"Events\\Delegates.cs\" />\r\n    <Compile Include=\"Activation\\ActivationHelper.cs\" />\r\n    <Compile Include=\"Helpers\\ObjectScrubber.cs\" />\r\n    <Compile Include=\"Helpers\\SmtpHelper.cs\" />\r\n    <Compile Include=\"Interfaces\\INameHolder.cs\" />\r\n    <Compile Include=\"Interfaces\\IFrame.cs\" />\r\n    <Compile Include=\"Events\\FrameEventArgs.cs\" />\r\n    <Compile Include=\"Events\\PayloadedEventArgs.cs\" />\r\n    <Compile Include=\"Helpers\\DateHelper.cs\" />\r\n    <Compile Include=\"Helpers\\EnumerableDataSources.cs\" />\r\n    <Compile Include=\"Helpers\\EnumHelper.cs\" />\r\n    <Compile Include=\"Helpers\\StringsHelper.cs\" />\r\n    <Compile Include=\"Interfaces\\IIndexable.cs\" />\r\n    <Compile Include=\"Interfaces\\INameable.cs\" />\r\n    <Compile Include=\"Collections\\NamedList.cs\" />\r\n    <Compile Include=\"Interfaces\\IText.cs\" />\r\n    <Compile Include=\"Events\\KeyChangedEventArgs.cs\" />\r\n    <Compile Include=\"DateTime\\DateRange.cs\" />\r\n    <Co mpile Include=\"DateTime\\EntityDateRange.cs\">\r\n      <SubType>Code</SubType>\r\n    </Compile>\r\n    <Compile Include=\"DateTime\\IMinimumBoundedDateRange.cs\" />\r\n    <Compile Include=\"DateTime\\IDateRange.cs\" />\r\n    <Compile Include=\"Enumerations.cs\" />\r\n    <Compile Include=\"DateTime\\IEntityDateRange.cs\" />\r\n    <Compile Include=\"Interfaces\\IUserNotifier.cs\" />\r\n    <Compile Include=\"Collections\\IXtendedEnumerable.cs\" />\r\n    <Compile Include=\"Membership.cs\" />\r\n    <Compile Include=\"DateTime\\MinimumBoundedDateRange.cs\" />\r\n    <Compile Include=\"Properties\\AssemblyInfo.cs\" />\r\n    <Compile Include=\"Properties\\Resources.Designer.cs\">\r\n      <AutoGen>True</AutoGen>\r\n      <DesignTime>True</DesignTime>\r\n     <DependentUpon>Resources.resx</DependentUpon>\r\n    </Compile>\r\n    <Compile Include=\"SeriesCube.cs\" />\r\n    <Compile Include=\"Collections\\XList.cs\" />\r\n  </ItemGroup>\r\n  <ItemGroup>\r\n    <Folder Include=\"Compression\\\" />\r\n  </Item Group>\r\n  <ItemGroup>\r\n    <EmbeddedResource Include=\"Properties\\Resources.resx\">\r\n      <Generator>ResXFileCodeGenerator</Generator>\r\n      <LastGenOutput>Resources.Designer.cs</LastGenOutput>\r\n    </EmbeddedResource>\r\n  </ItemGroup>\r\n  <Import Project=\"$(MSBuildToolsPath)\\Microsoft.CSharp.targets\" />\r\n  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. \r\n       Other similar extension points exist, see Microsoft.Common.targets.\r\n  <Target Name=\"BeforeBuild\">\r\n  </Target>\r\n  <Target Name=\"AfterBuild\">\r\n  </Target>\r\n  -->\r\n</Project>" 

?doc.Root.Name; {{http://schemas.microsoft.com/developer/msbuild/2003}Project}
        hashCode: 541551665
        localName: "Project"
        LocalName: "Project"
        Namespace: {http://schemas.microsoft.com/developer/msbuild/2003}
        NamespaceName: "http://schemas.microsoft.com/developer/msbuild/2003"
        ns: {http://schemas.microsoft.com/developer/msbuild/2003} 


?doc.Root.Descendants(); {System.Xml.Linq.XContainer.GetDescendants}
        name: null
        self: false
        System.Collections.Generic.IEnumerator<System.Xml.Linq.XElement>.Current: null
        System.Collections.IEnumerator.Current: null ?doc.Root.Nodes(); {System.Xml.Linq.XContainer.Nodes}
        System.Collections.Generic.IEnumerator<System.Xml.Linq.XNode>.Current: null
        System.Collections.IEnumerator.Current: null ?doc.Root.Attributes();

Upvotes: 2

Views: 2295

Answers (1)

Kirill Polishchuk
Kirill Polishchuk

Reputation: 56162

You're getting exception in this line:

Console.WriteLine("{0} {1}", el.Name, el.Attribute("id").Value);

because at least first child element of the root, in your sample it is PropertyGroup doesn't contain id attribute.

I can suugest you rewrite this line as

Console.WriteLine("{0} {1}", el.Name, (string)el.Attribute("id"));

In this case your code won't throw any exception.

Upvotes: 1

Related Questions