简体   繁体   中英

Using Linq to XML instead of XML Reader/Writer

I am trying to create a simple tool to parse an xml file and if/when a certain element is found it gets the value and then executes code using that value and then the executed code outputs a new value and then it is replaced and a new XML file is saved. It has proven to be alot more difficult then it seems to be worth.

Right now I am using a combination of XML reader and XML writer. It is very verbose and I seem to be having small issues, that are way to difficult to fix. You can see an example of my previous approach and it's code here.

I am wondering if someone can help me figure out how to use Linq to XML to do this job. I need to sift through the XML of the original document looking for "ClInclude" and "ClCompile" and when they are found I need to execute code and replace those attributes string with a new value. For a better example of what I am accomplishing, you can check the post prior to the last.

I have made many attempts and decided to ditch the reader/writer for good. Can anyone help me accomplish this? Here is an attempt I have made at the Linq to XML:

                string baseDir = (textBox2.Text + "\\" + safeFileName);
                string vcName = Path.GetFileName(textBox1.Text);
                string vcProj = Path.Combine(baseDir, vcName);

                XDocument xmlDoc = XDocument.Load(textBox1.Text);

                var items = from item in xmlDoc.Elements()
                            select item;

                foreach (XElement itemElement in items)
                {
                    if (itemElement.Name == "ClInclude")
                    {
                        // itemElement.SetElementValue("Include", "include/");
                        textBox3.AppendText(itemElement.Value);
                    }

                }

                xmlDoc.Save(vcProj);

Right now I am just appending them to a textbox, just to test it. I cannot seem to bring back any elements with Clinclude or ClCompile. Here is an example of the lines I am trying to get the value of and replace:

<ClCompile Include="..\..\lib\projx\conf.c" />
    <ClCompile Include="..\..\lib\projx\hash.c" />
    <ClCompile Include="..\..\lib\projx\init.c" />

Here is a full example of the XML I am parsing:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ItemGroup Label="ProjectConfigurations">
    <ProjectConfiguration Include="Debug|Win32">
      <Configuration>Debug</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
    <ProjectConfiguration Include="Release|Win32">
      <Configuration>Release</Configuration>
      <Platform>Win32</Platform>
    </ProjectConfiguration>
  </ItemGroup>
  <PropertyGroup Label="Globals">
    <ProjectGuid>{57900E99-A405-49F4-83B2-0254117D041B}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <RootNamespace>libprojx</RootNamespace>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v110</PlatformToolset>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <WholeProgramOptimization>true</WholeProgramOptimization>
    <CharacterSet>MultiByte</CharacterSet>
    <PlatformToolset>v110</PlatformToolset>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
  <ImportGroup Label="ExtensionSettings">
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
  </ImportGroup>
  <PropertyGroup Label="UserMacros" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LinkIncremental>true</LinkIncremental>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>WIN32;projx_EXPORTS;_DEBUG;_WINDOWS;_USRDLL;LIBprojx_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\Win32;..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <BasicRuntimeChecks>Default</BasicRuntimeChecks>
      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <AdditionalLibraryDirectories>..\..\..\..\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>libdirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>
      </PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;projx_EXPORTS;NDEBUG;_WINDOWS;_USRDLL;LIBprojx_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <AdditionalIncludeDirectories>..\..\Win32;..\..\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <AdditionalLibraryDirectories>..\..\..\..\Debug;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
      <AdditionalDependencies>libdirect.lib;%(AdditionalDependencies)</AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="..\..\lib\projx\conf.c" />
    <ClCompile Include="..\..\lib\projx\hash.c" />
    <ClCompile Include="..\..\lib\projx\init.c" />
    <ClCompile Include="..\..\lib\projx\shmalloc.c" />
    <ClCompile Include="..\..\lib\projx\shm\fake.c" />
    <ClCompile Include="..\..\lib\projx\vector.c" />
    <ClCompile Include="dllmain.c" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="..\..\lib\projx\conf.h" />
    <ClInclude Include="..\..\lib\projx\hash.h" />
    <ClInclude Include="..\..\lib\projx\shmalloc.h" />
    <ClInclude Include="..\..\lib\projx\types.h" />
    <ClInclude Include="..\..\lib\projx\vector.h" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

First you need to find your ClInclude, as I understood: var includs = xdoc.Descendants("ClInclude") will give you all ClInclude. If you need specific ClInclude with some special Include attribute value you do it like that:

var specificInclude = xdoc.Descendants("ClInclude")
      .Where(inc => inc.Attribute("Include").Value == yourValue).FirstOrDefault();

Next you need to replace Include attribute value with new one like this:

specificInclude.Attribute("Include").Value = newValue;

Full sample for console app:

string xml = @"<root><ItemGroup><ClInclude id=""1""></ClInclude><ClInclude id=""2""></ClInclude></ItemGroup></root>";

var newxDoc = XDocument.Parse(xml);

Console.WriteLine("Before");
Console.WriteLine(newxDoc.ToString());

var s = newxDoc.Descendants("ClInclude").Where(b => b.Attribute("id").Value == "2").FirstOrDefault();
s.Attribute("id").Value = "3";

Console.WriteLine("After");
Console.WriteLine(newxDoc.ToString());
Console.ReadLine();

Hope that helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM