widgetTests console output: What does the number after the `~` refer to? - flutter-test

We're running widgetTests and I'm seeing output like
:
00:08 +76: /Users/<path>/sliver_app_bar_test.dart: <test description>
00:08 +77 ~1: /Users/<path>/sliver_app_bar_test.dart: <test description>
00:08 +78 ~2: /Users/<path>/sliver_app_bar_test.dart: <test description>
00:08 +79 ~3: /Users/<path>/sliver_app_bar_test.dart: <test description>
00:08 +80 ~3: /Users/<path>/sliver_app_bar_test.dart: <test description>
:
00:33 +386 ~3: All tests passed!
The number after the + is the test counter. What's the number after the ~ refer to?

It's the number of skipped tests.

Related

How to solve NO_ROUTE_DESTINATION when connecting from two FreeSWITCH

I am new to FreeSWITCH and I am trying to bridge a call from two different FreeSWITCH (SwitchA -> SwitchB ).
But when I am trying to make a call, It says NO_ROUTE_DESTINATION .
Here is my current configuration for FreeSWITCH-A (the call originates)
My sip_profile/external
<include>
<gateway name="fs-test2">
<param name="proxy" value="ipOfSwitch-B:5080"/>
<param name="register" value="false"/>
<param name="called-id-in-from" value="true"/>
<variables>
<variable name="verbose_sdb" value="true"/>
<variable name="absolute_codec_string" value="PCMU, PCMA" direction="oubound"/>
</variables>
</gateway>
</include>
My DialPlan
dialplan/default
<include>
<extension name="outbound_call">
<condition field="destination_number" expression="^(18881)$">
<action application="bridge" data="sofia/gateway/fs-test2/$1"/>
</condition>
</extension>
</include>
dialplan/public
<include>
<extension name="public-did">
<condition field="destination_number" expression="^(19991)$">
<action application="set" data="domain_name=$${domain}"/>
<action application="transfer" data="1000 XML default"/>
<action application="answer"/>
<action application="sleep" data="1000"/>
</condition>
</extension>
</include>
And here is my current configuration for FreeSWITCH-B
My sip_profile/external
<include>
<gateway name="fs-test1">
<param name="proxy" value="ipOfSwitch-A:5080"/>
<param name="register" value="false"/>
<param name="caller-id-in-from" value="true"/>
</gateway>
</include>
My dialplan
dialplan/default
<include>
<extension name="outbound_call">
<condition field="destination_number" expression="^(18881)$">
<action application="bridge" data="sofia/gateway/fs-test1/$1"/>
</condition>
</extension>
</include>
dialplan/public
<include>
<extension name="public-did">
<condition field="destination_number" expression="^(18881)$">
<action application="set" data="domain_name=$${domain}"/>
<action application="transfer" data="1000 XML default"/>
</condition>
</extension>
</include>
This is my sofia status profile looks like in SWITCH A-
-----------------------------------------------------------------
Profile::Gateway-Name| Data | Status |
-----------------------------------------------------------------
external::fs-test2 | sip:FreeSWITCH#ipOfSwitchB:5080 | NOREG |
-----------------------------------------------------------------
This is my sofia status profile looks like in SWITCH B-
-----------------------------------------------------------------
Profile::Gateway-Name| Data | Status |
-----------------------------------------------------------------
external::fs-test1 | sip:FreeSWITCH#ipOfSwitchA:5080 | NOREG |
-----------------------------------------------------------------
and when I type the command for sofia status gateway fs-test2 in SWITCH A , the result looks like this:
Name | fs-test2
Profile | external
Scheme | Digest
Realm | ipOfSwitchB:5080
username | FreeSWITCH
Password | no
From | <sip:FreeSWITCH#ipOfSwitchB:5080>
Contact | <sip:gw+fs-test2#103.62.152.227:5080;transport=udp;gw=fs-test2>
Exten | FreeSWITCH
To | sip:FreeSWITCH#ipOfSwitchB:5080
Proxy | sip:FreeSWITCH#ipOfSwitchB:5080
Status | UP
State | NOREG
After I've done all the changes , I run "reloadxml", "reload mod_sofia"
When I trigger a call(18881) from SWITCH A, there is a logs showing on SWITCH B, and it says :
sofia.c:10362 sofia/external/FreeSWITCH#ipOfSWITCHB:5080 receiving invite from ipOfSWITCHB:5080 version: 1.10.6 -release-18-1ff9d0a60e 64bit call-id: fd37ba89-54d1-123a-db86-080027337ad5,
and the moment the call ended from SWITCHA, the logs shows on SWITCHA as:
switch_core_state_machine.c:276 Dialplan [default] not found, skipping
switch_core_state_machine.c:312 No Route, Aborting
switch_core_state_machine.c:313 Hangup sofia/external/1000#ipOfSWITCHA [CS_ROUTING] [NO_ROUTE_DESTINATION]
there is also a log showing on SwitchB:
sofia.c:8641 Hangup sofia/external/18881 [CS_CONSUME_MEDIA] [NO_ROUTE_DESTINATION]
mod_dptools.c:3643 Originate Failed. Cause: NO_ROUTE_DESTINATION
switch_channel.c:4942 Hangup sofia/external/FreeSWITCH#ipOfSwitchB:5080 [CS_EXECUTE] [NO_ROUTE_DESTINATION]
Am I missing something?
Thanks in advance.
I think this is what happened when SIP INVITE send into your Switch-B:
reach extension "public-did", and transfer to extension "1000" of default context.
since you don't have extension "1000" in default context, so you got error "No Route"

How to check if an attribute is present in an xml node using xmllint

I'm using bash and xmllint to check nodes in the following xml:
<?xml version="1.0" encoding="utf-8"?>
<output>
<document>
<sentence id="13">
<text>This is a test sentence.</text>
<entities>
<annotation id="3">
<grammar-form id="0" normal-form="THIS"/>
</annotation>
<annotation id="4">
<grammar-form id="0" normal-form="IS"/>
</annotation>
<annotation id="5">
<grammar-form id="0" normal-form="A"/>
</annotation>
<annotation id="6">
<grammar-form id="0" normal-form="TEST"/>
</annotation>
<annotation id="7">
<grammar-form id="0" normal-form="SENTENCE"/>
</annotation>
<annotation id="12">
<grammar-form id="0" normal-form="."/>
</annotation>
</entities>
</sentence>
</document>
</output>
How can I simply check that each grammar-form node has a normal-form attribute present? It doesn't matter what the attribute value is, I just need to check that it is present.
It's easier to select grammar-forms that don't have the attribute and see if you get any matches or not:
if xmllint --xpath '//grammar-form[not(#normal-form)]' input.xml 1>/dev/null 2>&1; then
echo "There are missing normal forms."
else
echo "There are no missing normal forms."
fi
In xpath mode, xmllint will print the matching paths, or if nothing matches, exit with a error code of 10 and print a message to that effect to standard error (the --noout option mentioned in the manpage to suppress output doesn't do anything in the version I'm testing with, unfortunately), hence the redirections.

How to redirect long string with single/double quotes var in Rundeck?

thank you for taking time reading this question.
I've a Rundeck job with multiple steps. Basically, step 1 and 2 is fetching a long string which is under ' '. Example:
'This is a long string.. and is also under "double quotes" '. -> This variable is stored as the following form: #option.mylongstring#
Third step of my Rundeck job is failing because I'm having issues with single and multiple quotes in my string. I want to extract specific values from that long string
My solution was to send the content of #option.mylongstring# in a temp file and apply sed to convert single quotes into double quotes (sed "s/'/\"/g") and from there, extract the information that I need.
Anyway, seems that the redirection is not happening in Rundeck: echo #option.mylongstring# &> $TEMPFILE is doing nothing, generating an empty file.
Anyone faced the same issue?
Using inline-script works without problems, let me share the job definition example:
<joblist>
<job>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>5e7123ce-c9b7-4bfa-a0e8-6484a9bd7c4f</id>
<loglevel>INFO</loglevel>
<name>LongStringExample</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<fileExtension>.sh</fileExtension>
<script><![CDATA[echo 'hello "world"' > myfile.txt]]></script>
<scriptargs />
<scriptinterpreter>/bin/bash</scriptinterpreter>
</command>
</sequence>
<uuid>5e7123ce-c9b7-4bfa-a0e8-6484a9bd7c4f</uuid>
</job>
</joblist>
Using an option:
<joblist>
<job>
<context>
<options preserveOrder='true'>
<option name='opt1' />
</options>
</context>
<defaultTab>nodes</defaultTab>
<description></description>
<executionEnabled>true</executionEnabled>
<id>22d7286f-7be9-4aaf-92ae-8e5bf5277d67</id>
<loglevel>INFO</loglevel>
<name>AnotherLongStringExample</name>
<nodeFilterEditable>false</nodeFilterEditable>
<plugins />
<scheduleEnabled>true</scheduleEnabled>
<sequence keepgoing='false' strategy='node-first'>
<command>
<fileExtension>.sh</fileExtension>
<script><![CDATA[echo 'this is another "#option.opt1#"' > another_file.txt]]></script>
<scriptargs />
<scriptinterpreter>/bin/bash</scriptinterpreter>
</command>
</sequence>
<uuid>22d7286f-7be9-4aaf-92ae-8e5bf5277d67</uuid>
</job>
</joblist>

Remote wsus querying with ansible : 401 unauthorized with valid accounts

I was writting my first powershell script to get statistics about around 300 servers dispatched on 3 WSUS servers. There's an upstream and two downstream servers (one autonomous and one replica).
The powershell script is sent to the upstream server before execution with the help of an ansible playbook (using winrm connection).
The script simply parses two configured hosts (the upstream and the autonomous downstream) then calls the Get-WsusServer and subsequent routines to get the data i need.
When the powershell script is ran directly on the upstream host, all is fine, and the Get-WsusServer with the autonomous server works.
When the powershell script is ran by the ansible playbook, it fails with the following error when the Get-WsusServer routine calls the autnonomous downstream server :
"stderr_lines": [
"Get-WsusServer : The request failed with HTTP status 401: Unauthorized.",
"At D:\\Reports\\wsusreport.ps1:74 char:11",
"+ $wsus = Get-WsusServer -Name $wsusserver -PortNumber 8530",
"+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
" + CategoryInfo : InvalidData: (Microsoft.Updat...usServerCommand:GetWsusServerCommand) [Get-WsusServer], ",
" WebException",
" + FullyQualifiedErrorId : ServerIsInvalid,Microsoft.UpdateServices.Commands.GetWsusServerCommand",
" ",
"You cannot call a method on a null-valued expression.",
"At D:\\Reports\\wsusreport.ps1:80 char:3",
"+ $classifications=$wsus.GetUpdateClassifications() |",
"+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
" + CategoryInfo : InvalidOperation: (:) [], RuntimeException",
" + FullyQualifiedErrorId : InvokeMethodOnNull",
" ",
"Exception calling \"AddRange\" with \"1\" argument(s): \"Value cannot be null.",
"Parameter name: value\"",
I tried using a domain account, with local admin privileges, and also with local admin accounts. But i cant put the finger on what the problem really is.
And i cant manage to explain the behavior difference between the local execution which is successful, and the execution with the playbook which fails when calling Get-WsusServer against the autonomous downstream server.
Additional information :
The powershell script loop looks like :
$Target_WSUS_Server_host = "upstream", "downstream"
foreach ($domain in $Target_WSUS_Server_Host) {
Write-Host "Working on : $domain"
[void][reflection.assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration')
$wsus = Get-WsusServer -Name $domain -PortNumber 8530
# Scope initialization
$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerscope.IncludeDownstreamComputerTargets = 'true'
etc....
The ansible piece of playbook is quite basic and just plays the win_shell module after the script is copied. If i only query the upstream, the ansible play is 100% OK.
---
- name: wsus report generation
hosts: upstream
vars:
local_dir: "./data/"
local_script: "wsusreport.ps1"
remote_script_log: "wsusreport.log"
remote_dir: 'D:\Reports\'
script_log: "wsusreport.log"
yearmonth: "{{ lookup('pipe', 'date +%Y-%m') }}"
tasks:
- name: copy ps1 script to wsus server
tags:
- sendscript
win_copy:
src: "{{ local_dir }}/{{ local_script }}"
dest: "{{ remote_dir }}"
- name: execute script
tags:
- exescript
win_shell: "{{ remote_dir }}\\{{ local_script }} downstream {{ yearmonth }} > {{ remote_dir }}\\{{ remote_script_log }}"
The powershell script takes two parameters,
first one is a switch to determine if i want just the upstream data, the downstream data or both.
the second one is the time range i wanna retrieve, which defaults to current patch tuesday campaign.
Additionnal information
On the security event log, what happens when the script is dropped and called by ansible :
- There's a logon/logout events with those details :
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2020-01-03T15:44:11.016233500Z" />
<EventRecordID>3662170</EventRecordID>
<Correlation ActivityID="{1715CB99-B4FA-0001-A1CB-1517FAB4D501}" />
<Execution ProcessID="792" ThreadID="4316" />
<Channel>Security</Channel>
<Computer>*FQDN of the downstream server*</Computer>
<Security />
</System>
- <EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-7</Data>
<Data Name="TargetUserName">ANONYMOUS LOGON</Data> <===== /!\
<Data Name="TargetDomainName">NT AUTHORITY</Data>
<Data Name="TargetLogonId">0x13316e110</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">NtLmSsp</Data>
<Data Name="AuthenticationPackageName">NTLM</Data>
<Data Name="WorkstationName">*Hostname of the upstream server*</Data>
<Data Name="LogonGuid">{00000000-0000-0000-0000-000000000000}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">NTLM V1</Data>
<Data Name="KeyLength">128</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">*IP Adress of the upstream server*</Data>
<Data Name="IpPort">55186</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1843</Data>
</EventData>
</Event>
When the script is called directly on the upstream server, the logon process is far more verbose, and uses the local account which is the same between the two servers.
- <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
<Provider Name="Microsoft-Windows-Security-Auditing" Guid="{54849625-5478-4994-A5BA-3E3B0328C30D}" />
<EventID>4624</EventID>
<Version>2</Version>
<Level>0</Level>
<Task>12544</Task>
<Opcode>0</Opcode>
<Keywords>0x8020000000000000</Keywords>
<TimeCreated SystemTime="2020-01-03T15:44:46.197671000Z" />
<EventRecordID>3662174</EventRecordID>
<Correlation ActivityID="{1715CB99-B4FA-0001-A1CB-1517FAB4D501}" />
<Execution ProcessID="792" ThreadID="5672" />
<Channel>Security</Channel>
<Computer>DOWNSTREAM_SERVER_FQDN</Computer>
<Security />
</System>
- <EventData>
<Data Name="SubjectUserSid">S-1-0-0</Data>
<Data Name="SubjectUserName">-</Data>
<Data Name="SubjectDomainName">-</Data>
<Data Name="SubjectLogonId">0x0</Data>
<Data Name="TargetUserSid">S-1-5-21-910770422-2570656215-934337312-1006</Data>
<Data Name="TargetUserName">ACCOUNT_USED_ON_BOTH_SERVERS</Data> <====== OK !
<Data Name="TargetDomainName">DOWNSTREAM_SERVER_HOSTNAME</Data>
<Data Name="TargetLogonId">0x13319dcbb</Data>
<Data Name="LogonType">3</Data>
<Data Name="LogonProcessName">NtLmSsp</Data>
<Data Name="AuthenticationPackageName">NTLM</Data>
<Data Name="WorkstationName">UPSTREAM_SERVER_HOSTNAME</Data>
<Data Name="LogonGuid">{00000000-0000-0000-0000-000000000000}</Data>
<Data Name="TransmittedServices">-</Data>
<Data Name="LmPackageName">NTLM V2</Data>
<Data Name="KeyLength">128</Data>
<Data Name="ProcessId">0x0</Data>
<Data Name="ProcessName">-</Data>
<Data Name="IpAddress">UPSTREAM_SERVER_IP_ADDRESS</Data>
<Data Name="IpPort">55198</Data>
<Data Name="ImpersonationLevel">%%1833</Data>
<Data Name="RestrictedAdminMode">-</Data>
<Data Name="TargetOutboundUserName">-</Data>
<Data Name="TargetOutboundDomainName">-</Data>
<Data Name="VirtualAccount">%%1843</Data>
<Data Name="TargetLinkedLogonId">0x0</Data>
<Data Name="ElevatedToken">%%1842</Data>
</EventData>
</Event>
Ok,
https://docs.ansible.com/ansible/latest/user_guide/windows_winrm.html#authentication-options
https://docs.ansible.com/ansible/2.5/user_guide/become.html#become-and-windows
The ntlm method doesnt let you assume the correct grants of the account you are using to run a win_shell command or instruction.
I had to swap ntlm for kerberos and use become feature with runas method, and specify the exact same account i'm using for the winrm connection.
It is working.

how to get the most deeply nested element nodes using xpath? (implementation with XMLTWIG)

I need to extract (XSLT, xpath, xquery... Preferably xpath) the most deeply nested element nodes with method (DEST id="RUSSIA" method="delete"/>) and his direct ancestor (SOURCE id="AFRICA" method="modify">).
I don't want to get the top nodes with methods ( main method="modify"> or main method="modify"> ).
The deepest nested elements with method correspond to real actions.
The top elements with method actually are dummy actions that must not be taken into account.
Here is my XML sample file:
<?xml version="1.0" encoding="UTF-8"?>
<main method="modify">
<MACHINE method="modify">
<SOURCE id="AFRICA" method="modify">
<DEST id="RUSSIA" method="delete"/>
<DEST id="USA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="AUSTRALIA" method="modify"/>
<DEST id="CANADA" method="create"/>
</SOURCE>
</MACHINE>
</main>
This is Xpath output I expect:
<SOURCE id="AFRICA" method="modify"><DEST id="RUSSIA" method="delete"/>
<SOURCE id="AFRICA" method="modify"><DEST id="USA" method="modify"/>
<SOURCE id="USA" method="modify"><DEST id="AUSTRALIA" method="modify"/>
<SOURCE id="USA" method="modify"><DEST id="CANADA" method="create"/>
My current xpath command does not provide the adequate result.
Command xpath("//[#method]/ancestor::*") which is returning:
<main><MACHINE method="modify"> # NOT WANTED
<MACHINE method="modify"><SOURCE id="AFRICA" method="modify"> # NOT WANTED
<MACHINE method="modify"><SOURCE id="USA" method="modify"> # NOT WANTED
<SOURCE id="AFRICA" method="modify"><DEST id="RUSSIA" method="delete"/>
<SOURCE id="AFRICA" method="modify"><DEST id="USA" method="modify"/>
<SOURCE id="USA" method="modify"><DEST id="AUSTRALIA" method="modify"/>
<SOURCE id="USA" method="modify"><DEST id="CANADA" method="create"/>
My xmltwig code for additional information (context):
#!/usr/bin/perl -w
use warnings;
use XML::Twig;
use XML::XPath;
#my $t= XML::Twig->new;
my $v= XML::Twig::Elt->new;
$t-> parsefile ('input.xml');
#abc=$t->get_xpath("\/\/[\#method]\/ancestor\:\:\*") ;
foreach $v (#abc) # outer 1
{
foreach $v ($v ->children) # internal 1
{
$w=$v->parent;
print $w->start_tag;
print $v->start_tag;
}
}
The nodes with maximum depth can be found with
//*[count(ancestor::*) = max(//*/count(ancestor::*))]
but it might perform horribly, depending how smart your optimizer is.
Having found those nodes, it is of course trivial to find their ancestors. But you are looking for output with more structure than XPath alone can provide.
As I mentioned in my comment on the question, I don't think this is possible with pure XPath as XPath doesn't have anything like a current() function that would allow to refer to the context outside of a [] restriction.
The most similar solution should be this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ZD="http://xyz.abc">
<xsl:output method="text"/>
<xsl:template match="//*">
<xsl:choose>
<xsl:when test="not(//*[count(ancestor::node()) > count(current()/ancestor::node())])"><xsl:value-of select="local-name(.)"/><xsl:text>
</xsl:text></xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="text()|#*"/>
</xsl:stylesheet>
The <xsl:when> element finds the most deeply nested elements. As an example, I'm outputting the local names of the found elements, followed by a newline, but of course you can output anything you need there.
Update: Note that this is based on XPath 1.0 knowledge/tools. It seems that this is indeed possible to express in XPath 2.0.
One such XPath2.0 expression is:
//*[not(*)
and
count(ancestor::*)
=
max(//*[not(*)]/count(ancestor::*))
]
/(self::node|..)
To illustrate this with a complete XSLT 2.0 example:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vResult" select=
"//*[not(*)
and
count(ancestor::*)
=
max(//*[not(*)]/count(ancestor::*))
]
/(self::node|..)
"/>
<xsl:template match="/">
<xsl:sequence select="$vResult"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<main method="modify">
<MACHINE method="modify">
<SOURCE id="AFRICA" method="modify">
<DEST id="RUSSIA" method="delete"/>
<DEST id="USA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="AUSTRALIA" method="modify"/>
<DEST id="CANADA" method="create"/>
</SOURCE>
</MACHINE>
</main>
the XPath expression is evaluated and the selected elements (the elements at maximum depth and their parents) are copied to the output:
<SOURCE id="AFRICA" method="modify">
<DEST id="RUSSIA" method="delete"/>
<DEST id="USA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="AUSTRALIA" method="modify"/>
<DEST id="CANADA" method="create"/>
</SOURCE>
The stylesheet
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates
select="//DEST[#method and not(node())]"/>
</xsl:template>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="DEST[#method and not(node())]">
<xsl:apply-templates select="..">
<xsl:with-param name="leaf" select="current()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="*[DEST[#method and not(node())]]">
<xsl:param name="leaf"/>
<xsl:copy>
<xsl:copy-of select="#* , $leaf"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
transforms
<?xml version="1.0" encoding="UTF-8"?>
<main method="modify">
<MACHINE method="modify">
<SOURCE id="AFRICA" method="modify">
<DEST id="RUSSIA" method="delete"/>
<DEST id="USA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="AUSTRALIA" method="modify"/>
<DEST id="CANADA" method="create"/>
</SOURCE>
</MACHINE>
</main>
into
<SOURCE id="AFRICA" method="modify">
<DEST id="RUSSIA" method="delete"/>
</SOURCE>
<SOURCE id="AFRICA" method="modify">
<DEST id="USA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="AUSTRALIA" method="modify"/>
</SOURCE>
<SOURCE id="USA" method="modify">
<DEST id="CANADA" method="create"/>
</SOURCE>

Resources