I think I see what you are after. Build variables created in the Variables tab of the GUI designer are scoped to the entire definition. But you can set a Job Scoped variable from a script within a GUI based pipeline.
So within the context of each of the Agent Jobs you have defined above, you would add a powershell task that would allow you to set the variable(s) that you then use for the automagic variable substitution in your xml.
YAML is better
If you want to go the YAML definition route you can actually create Job scoped variables directly in yaml. This example below substitutes against a JSON file but the concepts are similar for xml.
This is the Json file it substitutes against test.json
.
{
"menu": {
"id": "file",
"value": "File"
}
}
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: Production
variables:
- name: menu.id # Substituting this value in test.json
value: 'productionValue'
steps:
- task: FileTransform@1
displayName: 'File Transform:'
inputs:
folderPath: '$(System.DefaultWorkingDirectory)'
fileType: json
targetFiles: test.json
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Get-Content -Path test.json
- job: Staging
variables:
- name: menu.id # Substituting this value in test.json
value: 'stagingValue'
steps:
- task: FileTransform@1
displayName: 'File Transform:'
inputs:
folderPath: '$(System.DefaultWorkingDirectory)'
fileType: json
targetFiles: test.json
- task: PowerShell@2
inputs:
targetType: 'inline'
script: |
Get-Content -Path test.json
Custom Conditions
Another thing you might want to dig into is that Azure DevOps exposes task level custom conditions. You could add both transform tasks for Stage and Production to the pipeline definition and then only conditionally run the step you want. You could potentially collapse this into just one job and only build what you need to.
You need to decide on what that condition is. For example, you could do it based on the source branch (probably better) or just a variable that you can set at queue time.