Strucutre Configuration Variables - XPath add new attribute to element

Hi, I’m trying to use Structured Configuration Variables (XML) to add a new attribute to an existing element that already contains multiple attributes. I’m using the latest version of Octopus Server v2022.2
e.g. XML fragment:

<Connector port=“443” protocol=“org.apache.coyote.http11.Http11NioProtocol” maxThreads=“5000” SSLEnabled=“true” scheme=“https” secure=“true” SSLVerifyClient=“require” SSLEngine=“on” SSLVerifyDepth=“2” sslProtocol=“TLSv1.2” sslEnabledProtocols=“TLSv1.2” />

Can I target the Connector element to add a new attribute, e.g. maxConnections=“10000” which would give:
<Connector port=“443” protocol=“org.apache.coyote.http11.Http11NioProtocol” maxThreads=“5000” SSLEnabled=“true” scheme=“https” secure=“true” SSLVerifyClient=“require” SSLEngine=“on” SSLVerifyDepth=“2” sslProtocol=“TLSv1.2” sslEnabledProtocols=“TLSv1.2” maxConnections=“10000”/>

I’d prefer to avoid specifying all the existing attributes as part of the solution.

thanks

Hey @james.macdonald , thanks for reaching out, and welcome to the forum!

I want to clarify a couple of things to make sure I’m understanding your question, and that you have a solid knowledge of the Structured Variable Replacement feature.

Firstly, the structured variable replacement feature doesn’t currently support adding attributes. It’s specifically intended for replacement. That said, it also isn’t an “all-or-nothing” replacement! Here’s some sample XML that I tested with, adapted from our documentation on Structured Variable Replacement

<?xml version="1.0" encoding="UTF-8"?>
<server>
    <properties>
        <property name="host.name" value="localhost" />
    </properties>
</server>

Using that sample, I was able to define the following variable in my project:

During deployment, I saw in the logs:

Attempting structured variable replacement on file C:\Octopus\Applications\Development\xml-test\1.0.1_4\test.xml with format Xml 
June 20th 2022 15:56:16Verbose
Structure found matching the variable '/server/properties/property/@value'. Replacing its content with the variable value. 
June 20th 2022 15:56:16Info
Structured variable replacement succeeded on file C:\Octopus\Applications\Development\xml-test\1.0.1_4\test.xml with format Xml 

Then finally, the file as it was deployed:

<?xml version="1.0" encoding="utf-8"?>
<server>
  <properties>
    <property name="host.name" value="http://anythingelse" />
  </properties>
</server>

Following the above, you should be able to replace only the property you need to (in this case, maxConnections?). You can also confirm in the task logs that it’s evaluating and replacing the correct property!

Let me know if that makes sense and solves your issue, or if you still have questions. Happy to help however I can!

Hi Cory
Thanks for taking the time to reply. Yeah, I have already successfully replaced existing attributes and existing elements and it works very well for that use case. However, my use case was specifically to find an element using XPath and add a new attribute with value. So unfortunately this does not solve my issue. My only other thoughts are to either replace the entire element to include all the pre-existing attributes as well as the new one (not ideal), or find another approach, possibly using powershell.
cheers
James

Hey @james.macdonald , I was able to work out a way to get at it using PowerShell that should work for you here.

Same sample as above, but working to add a MaxConnections attribute. I’m using Deploy a Package, but any step that supports running scripts for packages should also work.

After enabling Custom Deployment Scripts, I added this script inline as the PreDeploy run:

$filePath = 'test.xml'
$nodePath = '/server/properties/property'

$xmlFile = [xml] (Get-Content $filePath)
$node = $xmlFile.SelectSingleNode($nodePath)

$attributeName = 'MaxConnections'

$attribute = $node.OwnerDocument.CreateAttribute($attributeName)
$node.Attributes.Append($attribute)
$xmlFile.Save($filePath)

That script adds the MaxConnections attribute to the location specified by $nodePath. Once added in PreDeploy, the structured variable replacement will correctly pick up on the empty value and replace it with the variable you’ve defined (in my case, I defined the variable path as /server/properties/property/@MaxConnections)

Hopefully that’s a workable solution! Let me know if that helps or if you run into any other challenges, happy to assist!