Andrey Bushman
Andrey Bushman

Reputation: 12516

What is syntax of nested property of MSBuild?

I am using MSBuild.

I am getting the value of the Person_1 through the $(Person_1). How can I get the value of the Name subelement of Person_2? I need the syntax.

<PropertyGroup>
  <Person_1>Bob</Person_1>
  <Person_2>
    <Name>Bob</Name>
  </Person_2>
</PropertyGroup>

Upvotes: 4

Views: 1804

Answers (3)

tm1
tm1

Reputation: 1319

You'll need something advanced, like an inline task:

<UsingTask TaskName="TransformXmlToItem" 
           TaskFactory="CodeTaskFactory"
           AssemblyName="Microsoft.Build.Tasks.Core">
  <ParameterGroup>
    <Xml Required="true"/>
    <Elements ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true"/>
  </ParameterGroup>
  <Task>
    <Reference Include="System.Xml" />
    <Using Namespace="System.Collections.Generic" />
    <Using Namespace="System.Xml" />
    <Code Type="Fragment" Language="cs">
      <![CDATA[  
        using (var xr = new XmlTextReader(Xml, XmlNodeType.Element,
            new XmlParserContext(null, null, null, XmlSpace.Default))) {

            xr.Namespaces = false;
            xr.MoveToContent();
            var items = new List<ITaskItem>();
            while (!xr.EOF) {
                if (xr.NodeType == XmlNodeType.Element) {
                    var item = new TaskItem(xr.Name);
                    var text = xr.ReadElementContentAsString();
                    if (!string.IsNullOrWhiteSpace(text)) {
                        item.SetMetadata("text", text);
                    }
                }
                xr.Read();
            }
            Elements = items.ToArray();
        }
    ]]>
  </Code>
</Task>

The task reads the XML elements and creates items from it. The text is transformed into metadata.

You can then write a task like this:

<Target Name="DeconstructPropertyXml">
  <TransformXmlToItem Xml="$(Person_2)">
    <Output TaskParameter="Elements" ItemName="Person_2I"/>
  </TransformXmlToItem>
  <Message Text="%(Person_2I.Identity) = %(Person_2I.text)" Importance="high"/>
</Target>

Which should just output Name = Bob.

The same way you could add additional metadata from attributes, etc.

Upvotes: 1

Donald Fraser
Donald Fraser

Reputation: 39

RE: https://msdn.microsoft.com/en-us/library/ms171458.aspx A property that contains XML is simply that. You cannot access parts of the content just because it is XML. To understand this do the following;

<PropertyGroup> 
   <MyProperty>
       <PropertyContentXML>
           <InnerXML1>Blablabla</InnerXML1>
           <InnerXML2>More blablabla</InnerXML2>
       </PropertyContentXML>
   </MyProperty>
</PropertyGroup> 
<Target Name="Build">
    <Message Text="$(MyProperty)" />
</Target>

The output of this will be:

<PropertyContentXML xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
        <InnerXML1>Blablabla</InnerXML1>
        <InnerXML2>More blablabla</InnerXML2>
</PropertyContentXML>

Upvotes: 3

oɔɯǝɹ
oɔɯǝɹ

Reputation: 7625

You are mixing Properties and ItemGroups.

Properties are simple named values, ItemGroups are items with an identity and with properties. You can not use both in the same way.

Properties are defined as :

<PropertyGroup>
    <name>value</name>
</Propertygroup>

and are accessed by using the $(name) syntax.

Item groups are defined as:

<ItemGroup>
    <Item Include="item1">
        <ItemPropery>value</ItemProperty>
    </Item>
</ItemGroup>

and are accessed by using this syntax: %(Item.ItemProperty).

See also this reference for the 'intuitive' syntax

Upvotes: 1

Related Questions