2013-10-30 27 views
0

我想創建一個簡單的工具來解析一個xml文件,如果/當某個元素被發現時,它會獲取該值,然後使用該值執行代碼,然後執行代碼輸出一個新值,然後替換它並保存一個新的XML文件。事實證明,這看起來很有價值,但這很困難。使用Linq到XML而不是XML讀寫器

現在我正在使用XML閱讀器和XML編寫器的組合。這是非常冗長的,我似乎有小問題,這是難以解決的方法。 You can see an example of my previous approach and it's code here.

我在想如果有人能幫我弄清楚如何使用Linq來做XML這個工作。我需要篩選原始文檔的XML,查找「ClInclude」和「ClCompile」,當它們被發現時,我需要執行代碼並用新值替換這些屬性字符串。 For a better example of what I am accomplishing, you can check the post prior to the last.

我已經做了很多嘗試,並決定把溝通的讀者/作家好。任何人都可以幫我完成這件事?以下是我在做的LINQ到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); 

現在,我只是他們附加到一個文本框,只是爲了測試它。我似乎無法帶回Clinclude或ClCompile中的任何元素。這裏是我試圖獲得的價值,並更換線路的例子:

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

這裏是我解析XML的一個完整的例子:

<?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> 
+0

看看重載xmlDoc.Elements();你應該能夠在那裏指定一個名字並且只有那些元素的結果。另外,你的行與SQL語法?這可以只是'items = xmlDoc.Elements()'。你也可以看看.Descendants – Magus

回答

1

首先你要找到你ClInclude,據我所知:var includs = xdoc.Descendants("ClInclude")會給你所有的ClInclude。如果您需要特定ClInclude一些特殊包含屬性值,你那樣做:

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

接下來你需要替換包括與新的這樣的屬性值:

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

控制檯應用程序全部樣本:

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(); 

希望有所幫助!

+0

很好的答案。我當時必須錯過它。不知道它是如何發生的。非常抱歉。 – user1632018