简体   繁体   English

用XML导航项目文件

[英]Navigating project files in XML

I am looking to parse and modify a project file of type .dbproj . 我正在寻找解析和修改.dbproj类型的项目文件。

Sample XML 样本XML

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ProjectGroup></ProjectGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup>
      <Build Include="myfile.cs">
           <SubType>Code</SubType>
          </Build>
      <Build Include="myfile2.cs">
           <SubType>Code</SubType>
          </Build>
      <Build Include="myfile3.cs">
           <SubType>Code</SubType>
          </Build>
    </ItemGroup>
    <ItemGroup>
      <NotInBuild Include="myfile4.cs">
        <SubType>Code</SubType>
      </NotInBuild>
    </ItemGroup>
</Project>

I want to take the item from the 4th <ItemGroup> with the attribute Include="myfile.cs" and remove it from said <ItemGroup> . 我想从第4个<ItemGroup>具有Include="myfile.cs"属性的项目,并将其从所说的<ItemGroup>删除。 Next, I want to add this element: 接下来,我要添加此元素:

<NotInBuild Include="myfile.cs">
    <SubType>Code</SubType>
</NotInBuild>

It is slightly modified from the one removed to the 5th ItemGroup . 从删除到第5个ItemGroup略有修改。 The result should be: 结果应为:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
    <ProjectGroup></ProjectGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup></ItemGroup>
    <ItemGroup>
      <Build Include="myfile2.cs">
           <SubType>Code</SubType>
          </Build>
      <Build Include="myfile3.cs">
           <SubType>Code</SubType>
          </Build>
    </ItemGroup>
    <ItemGroup>
      <NotInBuild Include="myfile.cs">
        <SubType>Code</SubType>
      </NotInBuild>
      <NotInBuild Include="myfile4.cs">
        <SubType>Code</SubType>
      </NotInBuild>
    </ItemGroup>
</Project>

Per another SO post by Skeet, I started going down the LINQ path.I don't know where to go from here 在Skeet的另一篇SO帖子中 ,我开始沿着LINQ道路走下去,我不知道从这里去哪里。

XDocument doc = XDocument.Load(XmlDocumentPath);
XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003";
                var query = doc.Root          
                .Elements(ns + "ItemGroup");

Using this collection class and the associated extensions: http://searisen.com/xmllib/xelementcollection.wiki 使用此收集类和相关的扩展: http : //searisen.com/xmllib/xelementcollection.wiki

And these classes: 这些类:

public class Project
{
    XElement self;
    public Project(FileInfo file)
    {
        self = XElement.Load(file.FullName);
    }

    public ItemGroup[] ItemGroup
    {
        get
        {
            return _ItemGroup
                ?? (_ItemGroup = self.GetEnumerable("ItemGroup", x => new ItemGroup(x)).ToArray());
        }
    }
    ItemGroup[] _ItemGroup;
}

public class ItemGroup
{
    XElement self;
    public ItemGroup(XElement self)
    {
        this.self = self;
    }

    public XElementCollection Build
    {
        get
        {
            return _Build
                ?? (_Build = new XElementCollection(self, "Build",
                         (a, b) => a.Get("Include", string.Empty) ==
                                   b.Get("Include", string.Empty),
                         false));
        }
    }
    XElementCollection _Build;

    public XElementCollection NotInBuild
    {
        get
        {
            return _NotInBuild
                ?? (_NotInBuild = new XElementCollection(self, "NotInBuild",
                         (a, b) => a.Get("Include", string.Empty) ==
                                   b.Get("Include", string.Empty),
                         false));
        }
    }
    XElementCollection _NotInBuild;
}

Then this sort of messy implementation: 然后是这种凌乱的实现:

Project project = new Project(xmlFile2);
XElement find = null;
ItemGroup item = project.ItemGroup.FirstOrDefault(i =>
    (find = i.Build.Find(x => x.Get("Include", string.Empty) == "myfile.cs")) != null);
if (null != find)
{
    XElement not = new XElement(find.Name.Namespace + "NotInBuild");
    not.Set("Include", "myfile.cs", true);
    foreach (var child in find.Elements().ToArray())
        not.Add(child);
    find.Remove();
    ItemGroup notGroup = project.ItemGroup.FirstOrDefault(i => i.NotInBuild.Count > 0);
    notGroup.NotInBuild.Add(not);
}

Using the extension methods mentioned at the top, the namespace issue is a non-issue. 使用顶部提到的扩展方法,名称空间问题不是问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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