我正在尝试读取XML文件,并根据我想要执行某些代码的元素的值,然后将值替换为生成的代码,然后将文件保存到新位置。
我目前正在这样做的方式非常冗长且不准确,并且变成了一个大麻烦。我想要做的是修改“ClInclude”和“ClCompile”元素。当找到它们时,我想执行一些代码,然后用新的代码替换当前值而不是保存它们。我更喜欢使用linq to xml方法而不是我的XML reader和Writer方法。以下是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>
以下是我目前正在使用的工作:
string vcName = Path.GetFileName(textBox1.Text);
string vcProj = Path.Combine(baseDir, vcName);
using (XmlReader reader = XmlReader.Create(textBox1.Text))
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.ConformanceLevel = ConformanceLevel.Auto;
settings.Indent = true;
settings.CloseOutput = false;
string nameSpace = "http://schemas.microsoft.com/developer/msbuild/2003";
using (XmlWriter writer = XmlWriter.Create(vcProj, settings))
{
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "ClInclude")
{
//execute code here- omitted for example
writer.WriteStartElement(reader.Name, nameSpace);
writer.WriteAttributeString("Include", "include/" + filename);
writer.WriteEndElement();
}
else if (reader.Name == "ClCompile" && reader.HasAttributes)
{
//execute code here- omitted for example
writer.WriteStartElement(reader.Name, nameSpace);
writer.WriteAttributeString("Include", "src/" + filename);
writer.WriteEndElement();
}
else
{
writer.WriteStartElement(reader.Name, nameSpace);
writer.WriteAttributes(reader, true);
}
break;
case XmlNodeType.Text:
writer.WriteString(reader.Value);
break;
case XmlNodeType.XmlDeclaration:
case XmlNodeType.ProcessingInstruction:
writer.WriteProcessingInstruction(reader.Name, reader.Value);
break;
case XmlNodeType.Comment:
writer.WriteComment(reader.Value);
break;
case XmlNodeType.Attribute:
writer.WriteAttributes(reader, true);
break;
case XmlNodeType.EntityReference:
writer.WriteEntityRef(reader.Value);
break;
case XmlNodeType.EndElement:
writer.WriteFullEndElement();
break;
}
}
}
答案 0 :(得分:0)
抱歉,为什么你不能使用微软推荐使用的新STUFF?我举个例子。添加
using System.IO;
using System.Xml.Linq;
假设你有一个xml文件
<?xml version="1.0" encoding="utf-8" ?>
<Root>
<Employee>
<Name>
John
</Name>
<Last>
Smith
</Last>
<Email>
js@gmail.com
</Email>
</Employee>
<Employee>
<Name>
Danial
</Name>
<Last>
Black
</Last>
<Email>
db@gmail.com
</Email>
</Employee>
<Employee>
<Name>
Marry
</Name>
<Last>
Sweet
</Last>
<Email>
ms@gmail.com
</Email>
</Employee>
</Root>
您想修改每个员工中的姓名
XDocument xDoc = XDocument.Load(@"C:\example.xml");
xDoc.Descendants(XName.Get("Employee")).ToList().ForEach(x =>
{
string name = x.Element(XName.Get("Name")).Value;
x.Element(XName.Get("Name")).Value = name + " Junior";
});
xDoc.Save(@"C:\result.xml");
就是这样!
答案 1 :(得分:0)
如果您想将LINQ to XML用于此目的,那么您的代码可能如下所示:
var input = @"d:\temp\in.xml";
var output = @"d:\temp\out.xml";
try
{
// load original file
var xmlDocument = XDocument.Load(input);
// don't forget to take the namespace, otherwise LINQ will not find the elements
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
// finder helper
Func<string, IEnumerable<XElement>> getElements = elementName =>
// find all elements of type ItemGroup
// that contain elements of the given type (here ClInclude or ClCompile)
xmlDocument.Root.Elements(ns + "ItemGroup").Elements(ns + elementName);
// find elements: ClInclude
var clInputs = getElements("ClInclude");
foreach (var clInput in clInputs)
{
// fetch attribute
var inputAttribute = clInput.Attributes("Include");
// take first and modify it
inputAttribute.ElementAt(0).Value = "some new value";
}
// find elements: ClCompile
var clCompiles = getElements("ClCompile");
foreach (var clCompile in clCompiles)
{
// fetch attribute
var compileAttribute = clCompile.Attributes("Include");
// take first and modify it
compileAttribute.ElementAt(0).Value = "some other value";
}
// save modified file under new name
xmlDocument.Save(output);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
新输出中的修改部分如下所示:
<ItemGroup>
<ClCompile Include="some other value" />
<ClCompile Include="some other value" />
...
<ClCompile Include="some other value" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="some new value" />
...
<ClInclude Include="some new value" />
</ItemGroup>
可以找到有关LINQ to XML的更多信息at MSDN。
答案 2 :(得分:0)
好的,你刚忘了Namespace
此示例使用您的xml
XElement xElement = XElement.Load(@"C:\target.xml");
string ns = xElement.Name.Namespace.NamespaceName;
xElement.Descendants(XName.Get("ClCompile", ns)).ToList().ForEach(x =>
{
XAttribute xAttr = x.Attribute(XName.Get("Include"));
if (xAttr != null)
{
string name = xAttr.Value;
xAttr.Value = name + "?modified";
}
});
xElement.Descendants(XName.Get("ClInclude", ns)).ToList().ForEach(x =>
{
XAttribute xAttr = x.Attribute(XName.Get("Include"));
if (xAttr != null)
{
string name = xAttr.Value;
xAttr.Value = name + "?included";
}
});
xElement.Save(@"C:\result.xml");
所以我只是在具有Include属性的标签上添加一个字符串!