In an MSBuild target, I need to set the value of an XML element to a specific value. If that element does not exist I need to create it. I'm trying to achieve this using MSBuild's XmlPoke
task but it only works if the element exists already. Here's an example:
XML content to update:
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<metadata>
<name>whatever</name>
<version>1.2.3.4</version>
</metadata>
</manifest>
Using XmlPoke
as shown below, I can successfully set the value of the version
element:
<XmlPoke
XmlInputPath="$(XmlFilePath)"
Query="/manifest/metadata/version"
Value="4.3.2.1" />
The result of that looks as follows:
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<metadata>
<name>whatever</name>
<version>4.3.2.1</version>
</metadata>
</manifest>
However, if the input is missing the version
element, as shown below, the XmlPoke
task just doesn't do anything:
<?xml version="1.0" encoding="utf-8"?>
<manifest>
<metadata>
<name>whatever</name>
</metadata>
</manifest>
How can I create the version
element and set it to 4.3.2.1
if it does not exist or just set it to 4.3.2.1
if it does exist using MSBuild standard functionality?
Edit:
The accepted answer with combining both XmlPeek
and XmlPoke
works. Based on that answer, here's the code that inserts or updates the value:
<XmlPeek
XmlInputPath="$(XmlFilePath)"
Query="/manifest/metadata/version">
<Output
TaskParameter="Result"
ItemName="VersionEntry" />
</XmlPeek>
<XmlPoke
Condition="'@(VersionEntry)' != ''"
XmlInputPath="$(XmlFilePath)"
Query="/manifest/metadata/version"
Value="4.3.2.1" />
<XmlPoke
Condition="'@(VersionEntry)' == ''"
XmlInputPath="$(XmlFilePath)"
Query="/manifest/metadata"
Value="<Name>whatever</Name><Version>4.3.2.1</Version>" />
XmlPoke
uses the specified XPath, the Query
, to find matching nodes. If it finds a node, it replaces the InnerXml
with the specified Value
. It will do this for each match. If there are no matches, XmlPoke
does nothing.
An approach using standard MSBuild functionality:
Use XmlPeek
to test for /manifest/metadata/version
.
If version
exists, then use XmlPoke
to update.
If version
does not exist:
XmlPeek
to get the contents of /manifest/metadata
.metadata
with <version>$(ver)</version>
appended.XmlPoke
to update /manifest/metadata
.If that seems cumbersome, you could write an inline task that 'upserts' the version.