Here is the fixed version of my previous code (@moderators , please delete my previous note )Returns a more comprehensive array of SOAP Client types as an array<?PHPfunction read_wsdl_types( SoapClient $soap ): array { $wsdl_types = $soap->__getTypes(); $lookup = array(); $regexes = array( 'atomic' => '/^([\w_]+)\s([\w_]+)$/mi', 'list' => '/^([\w_]+)\s([\w_]+)[ {]+([\w_]+)[ }]+$/mi', 'struct' => '/([\w_]+)\s([\w_]+)[\s{]?([\w_]+)*[\s;}]?/mi', ); foreach ( array_reverse( $wsdl_types ) as $wsdl_type ) { $matches = array(); foreach ( $regexes as $type => $regex ) { if ( preg_match_all( $regex, $wsdl_type, $matches ) ) { break; } } if ( !empty( $matches[1] ) && !empty( $matches[2] ) ) { switch ( $type ) { case 'atomic': $name = array_shift( $matches[2] ); $data_type = array_shift( $matches[1] ); $lookup[ $name ] = array( 'name' => $name, 'type' => $type, 'data_type' => $data_type, 'items' => array(), ); break; case 'list': $name = array_shift( $matches[2] ); $type = array_shift( $matches[1] ); $items = array_shift( $matches[3] ); $lookup[ $name ] = array( 'name' => $name, 'type' => $type, 'data_type' => $items, 'items' => array( array( 'name' => '', 'data_type' => $items, ), ), ); break; case 'struct': $name = array_shift( $matches[2] ); $type = array_shift( $matches[1] ); $items = array(); foreach ( $matches[2] as $key => $item_name ) { $items[ $key ] = array( 'name' => $item_name, 'data_type' => $matches[1][ $key ], ); } $lookup[ $name ] = array( 'name' => $name, 'type' => $type, 'data_type' => $name, 'items' => $items, ); break; } } } array_walk( $lookup, function ( &$type, $key, $data ) { if ( !empty( $type['items'] ) ) { array_walk( $type['items'], function ( &$item, $key, $data ) { if ( !empty( $item['data_type'] ) ) { $old_data_type = $item['data_type']; $item['type'] = $data[ $old_data_type ]['type'] ?? 'atomic'; $item['data_type'] = $data[ $old_data_type ]['data_type'] ?? $old_data_type; $item['from'] = $data[ $old_data_type ]['name'] ?? ''; } }, $data ); } }, $lookup ); return array_reverse( $lookup );}?>