如何使用MSBuild创建一个XML文件?

20
我想在MSBuild任务中创建一个XML文件。
我有一个文件列表:
<CreateItem Include="$(TestsAssembliesOutputDir)\Emidee.*.Tests.dll">
  <Output ItemName="TestsAssemblies" TaskParameter="Include" />
</CreateItem>

我想创建一个类似于以下结构的XML:

<?xml version="1.0" encoding="utf-8"?>
<xunit>
  <assemblies>
    <assembly filename="PATH OF FILE #1" shadow-copy="true" />
    <assembly filename="PATH OF FILE #2" shadow-copy="true" />
  </assemblies>
</xunit>

我该怎么做才能实现这个目标?

先谢谢啦!

Mike

4个回答

31

快速且简单...

<Target Name="CreateXml">
  <ItemGroup>
    <TestAssembly Include="$(TestsAssembliesOutputDir)\Emidee.*.Tests.dll" />
    <Line Include="line01"><Text>&lt;xunit&gt;</Text></Line>
    <Line Include="line02"><Text>&lt;assemblies&gt;</Text></Line>
    <Line Include="line03"><Text>&lt;assembly filename=&quot;%(TestAssembly.Identity)&quot; shadow-copy=&quot;true&quot; /&gt;</Text></Line>
    <Line Include="line04"><Text>&lt;/assemblies&gt;</Text></Line>
    <Line Include="line05"><Text>&lt;/xunit&gt;</Text></Line>
    <LineText Include="%(Line.Text)" />
  </ItemGroup>
  <WriteLinesToFile
     File="out.xml"
     Lines="@(LineText)"
     Overwrite="true"
     />
</Target>

留给你作为一项练习

  • 初始的<?xml 行
  • 缩进(建议在<Text>中使用CDATA)

你还可以在WriteLinesToFile中使用以下内容,省略合成的@(LineText)

    Lines="@(Line->'%(Text)')"

2

一种选择是使用内联任务。这允许您编写任意的C#代码来生成Xml,这可能比其他解决方案更容易(或更难)。以下是我在构建中使用来拼凑NuGet nuspec文件的示例。

...
<UsingTask
        TaskName="CreateNugetPackage"
        TaskFactory="CodeTaskFactory"
        AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll"
    >
        <ParameterGroup>
            <ProjectName ParameterType="System.String" Required="true" />
            <Version ParameterType="System.String" Required="true" />
            <BaseFolder ParameterType="System.String" Required="true" />

            <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
            <OutputFile ParameterType="Microsoft.Build.Framework.ITaskItem" Required="true" />
        </ParameterGroup>

        <Task>
            <Reference Include="System.Xml" />
            <Using Namespace="System" />
            <Using Namespace="System.Xml" />
            <Code Type="Fragment" Language="cs">
                <![CDATA[
                var root = Path.GetFullPath(BaseFolder);    

                using (var w = XmlWriter.Create(OutputFile.ItemSpec)) {
                    var ns = "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd";
                    w.WriteStartElement("package", ns);

                    w.WriteStartElement("metadata");

                    w.WriteStartElement("id");
                    w.WriteValue(ProjectName);
                    w.WriteEndElement();
                    w.WriteStartElement("version");
                    w.WriteValue(Version);
                    w.WriteEndElement();
                    w.WriteStartElement("description");
                    w.WriteValue("Test");
                    w.WriteEndElement();

                    w.WriteStartElement("authors");
                    w.WriteValue("Test");
                    w.WriteEndElement();

                    w.WriteEndElement();


                    w.WriteStartElement("files");

                    foreach(var file in Files) {
                        w.WriteStartElement("file");
                        var inFile = file.ItemSpec;
                        inFile = inFile.Replace(root, "");
                        w.WriteAttributeString("src", inFile);
                        w.WriteAttributeString("target", inFile);
                        w.WriteEndElement();
                    }

                    w.WriteEndElement();

                    w.WriteEndElement();
                }

    ]]>
            </Code>
        </Task>
    </UsingTask>


    <Target Name="CreateNuspec" BeforeTargets="BuildNugetPackage">

       <CreateNugetPackage
            Files="@(Artifacts)"
            OutputFile="$(NugetPackageSpec)"
            ProjectName="$(ProjectName)"
            BaseFolder="$(ArtifactRoot)"
            Version="$(Version)"
            />
    </Target>
...

一些相关文档:

UsingTaskElement

MSBuild内联任务


1

新版本的Brian解决方案包含“initial < ? xml line”,不包含“Text”和编码引号:

<Target Name="CreateXml">
  <ItemGroup>
    <TestAssembly Include="$(TestsAssembliesOutputDir)\Emidee.*.Tests.dll" />
    <Line Include='&lt;%3Fxml version="1.0" encoding="utf-8"%3F&gt;' />
    <Line Include='&lt;xunit&gt;' />
    <Line Include='&lt;assemblies&gt;' />
    <Line Include='&lt;assembly filename="%(TestAssembly.Identity)" shadow-copy="true" /&gt;' />
    <Line Include='&lt;/assemblies&gt;' />
    <Line Include='&lt;/xunit&gt;' />
  </ItemGroup>
  <WriteLinesToFile
     File="out.xml"
     Lines="@(Line)"
     Overwrite="true"
     />
</Target>

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接