Reputation: 12142
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
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