function createControls(node, pRequireContext, oClosestBinding, oAggregation, oConfig) {
			var bRootArea = oConfig && oConfig.rootArea,
				bRootNodeInSubView = oConfig && oConfig.rootNode && oView.isSubView(),
				sLocalName = localName(node),
				bRenderingRelevant = bRootArea && (oView.isA("sap.ui.core.Fragment") || (oAggregation && oAggregation.name === "content")),
				pResult, i;

			/**
			 * @ui5-transform-hint replace-local false
			 */
			const bRenderText = node.nodeType === 3 /* TEXT_NODE */ && bRenderingRelevant;

			if ( node.nodeType === 1 /* ELEMENT_NODE */ ) {
				// Using native HTML in future is not allowed. We need to check explicitely in order to throw
				if (node.namespaceURI === XHTML_NAMESPACE || node.namespaceURI === SVG_NAMESPACE) {
					future.warningThrows(`${oView.getId()}: Using native HTML content in XMLViews is deprecated.`);
				}
				/**
				 * Differentiate between SAPUI5 and plain-HTML children
				 * @ui5-transform-hint replace-local false
				 */
				const isNativeContent = node.namespaceURI === XHTML_NAMESPACE || node.namespaceURI === SVG_NAMESPACE;
				if (isNativeContent) {
					if (bRootArea) {
						if (oAggregation && oAggregation.name !== "content") {
							Log.error(createErrorInfo(node, "XHTML nodes can only be added to the 'content' aggregation and not to the '" + oAggregation.name + "' aggregation."));
							return SyncPromise.resolve([]);
						}

						if (oConfig && oConfig.contentBound) {
							throw new Error(createErrorInfo(node, "No XHTML or SVG node is allowed because the 'content' aggregation is bound."));
						}

						var bXHTML = node.namespaceURI === XHTML_NAMESPACE;

						// determine ID
						var sId = node.getAttribute("id");
						if ( sId != null ) {
							sId = getId(oView, node);
						} else {
							sId = bRootNodeInSubView ? oView.getId() : undefined;
						}

						if ( sLocalName === "style" ) {
							// We need to remove the namespace prefix from style nodes
							// otherwise the style element's content will be output as text and not evaluated as CSS
							// We do this by manually 'cloning' the style without the namespace prefix

							// original node values
							var aAttributes = node.attributes; // array-like 'NamedNodeMap'
							var sTextContent = node.textContent;

							// 'clone'
							node = document.createElement(sLocalName);
							node.textContent = sTextContent;

							// copy all non-prefixed attributes
							//    -> prefixed attributes are invalid HTML
							for (i = 0; i < aAttributes.length; i++) {
								var oAttr = aAttributes[i];
								if (!oAttr.prefix) {
									node.setAttribute(oAttr.name, oAttr.value);
								}
							}
							// avoid encoding of style content by writing the whole tag as unsafeHtml
							// for compatibility reasons, apply the same ID rewriting as for other tags
							if ( sId != null ) {
								node.setAttribute("id", sId);
							}
							if ( bRootNodeInSubView ) {
								node.setAttribute("data-sap-ui-preserve", oView.getId());
							}
							rm.unsafeHtml(node.outerHTML);
							return SyncPromise.resolve([]);
						}
						// write opening tag
						var bVoid = rVoidTags.test(sLocalName);
						if ( bVoid ) {
							rm.voidStart(sLocalName, sId);
						} else {
							rm.openStart(sLocalName, sId);
						}
						// write attributes
						for (i = 0; i < node.attributes.length; i++) {
							var attr = node.attributes[i];
							// id and core:require should not be output to DOM
							if ( attr.name !== "id" && (attr.localName !== "require" || attr.namespaceURI !== CORE_NAMESPACE)) {
								rm.attr(bXHTML ? attr.name.toLowerCase() : attr.name, attr.value);
							}
						}
						if ( bRootNodeInSubView ) {
							rm.attr("data-sap-ui-preserve", oView.getId());
						}
						if ( bVoid ) {
							rm.voidEnd();
							if ( node.firstChild ) {
								Log.error("Content of void HTML element '" + sLocalName + "' will be ignored");
							}
						} else {
							rm.openEnd();

							var pSelfRequireContext = parseAndLoadRequireContext(node, bAsync);

							if (pSelfRequireContext) {
								pRequireContext = SyncPromise.all([pRequireContext, pSelfRequireContext])
									.then(function(aContexts) {
										return Object.assign({}, ...aContexts);
									});
							}

							// write children
							// For HTMLTemplateElement nodes, skip the associated DocumentFragment node
							var oContent = node instanceof HTMLTemplateElement ? node.content : node;

							var handleChildren = getHandleChildrenStrategy(function (node, childNode, mOptions) {
								return createControls(childNode, mOptions.chain, mOptions.closestBinding, mOptions.aggregation, mOptions.config);
							}, bAsync);

							pResult = handleChildren(oContent, {
								chain: pRequireContext,
								closestBinding: oClosestBinding,
								aggregation: oAggregation,
								config: { rootArea: bRootArea }
							});


							return pResult.then(function(aResults) {
								rm.close(sLocalName);

								// aResults can contain the following elements:
								//  * require context object
								//  * array of control instance(s)
								//  * undefined
								return aResults.reduce(function(acc, vControls) {
									if (Array.isArray(vControls)) {
										vControls.forEach(function(oControl) {
											acc.push(oControl);
										});
									}
									return acc;
								}, []);
							});
						}
					} else {
						var id = node.attributes['id'] ? node.attributes['id'].textContent || node.attributes['id'].text : null;

						if (bEnrichFullIds) {
							return XMLTemplateProcessor.enrichTemplateIdsPromise(node, oView, bAsync).then(function(){
								// do not create controls
								return [];
							});
						} else {
							// plain HTML node - create a new View control
							// creates a view instance, but makes sure the new view receives the correct owner component
							var fnCreateView = function (oViewClass, oRequireContext) {
								var mViewParameters = {
									id: id ? getId(oView, node, id) : undefined,
									xmlNode: node,
									requireContext: oRequireContext,
									containingView: oView._oContainingView
								};

								/**
								 * @deprecated because the 'Sequential' Mode is used by default and it's the only mode that will be supported
								 * in the next major release
								 *
								 * add processing mode, so it can be propagated to subviews inside the HTML block
								 */
								mViewParameters.processingMode = oView._sProcessingMode;

								// running with owner component
								return scopedRunWithOwner(function() {
									return new oViewClass(mViewParameters);
								});
							};

							return pRequireContext.then(function(oRequireContext) {
								if (bAsync) {
									return new Promise(function (resolve, reject) {
										sap.ui.require(["sap/ui/core/mvc/XMLView"], function(XMLView) {
											resolve([fnCreateView(XMLView, oRequireContext)]);
										}, reject);
									});
								} else {
									var XMLView = sap.ui.requireSync("sap/ui/core/mvc/XMLView"); // legacy-relevant: Sync path
									return [fnCreateView(XMLView, oRequireContext)];
								}
							});
						}
					}

				} else  {
					pResult = createControlOrExtension(node, pRequireContext, oClosestBinding);
					if (bRenderingRelevant) {
						collectControl(pResult);
					}
					// non-HTML (SAPUI5) control
					// we must return the result in either bRootArea=true or the bRootArea=false case because we use the result
					// to add the control to the aggregation of its parent control
					return pResult;
				}
			} else if (bRenderText) {
				if (!oConfig || !oConfig.contentBound) {
					// content aggregation isn't bound
					rm.text(node.textContent);
				} else if (node.textContent.trim()) {
					throw new Error(createErrorInfo(node, "Text node isn't allowed because the 'content' aggregation is bound."));
				}
			}

			return SyncPromise.resolve([]);
		}
Takes an arbitrary node (control or plain HTML) and creates zero or one or more SAPUI5 controls from it,
iterating over the attributes and child nodes.

@param {Element} node The current XMLNode which is being processed
@param {Promise} pRequireContext Promise which resolves with the loaded modules from require context
@param {object} [oClosestBinding] Information on the binding that is closest to currently processed control
 node. Used by the flex extension-point provider to correctly trigger aggregation updates. This is necessary
 for extension-points that are inside a template control of an aggregation.
@param {Object} [oAggregation] The information of the aggregation to which the control being processed will be added
@param {object} [oConfig] The config object that contains information which is forwarded during the recursive processing
@param {boolean} [oConfig.rootArea=false] Indicates whether it's processing the root area of an XMLView
@param {boolean} [oConfig.rootNode=false] Indicates whether the <code>node</code> is the root node of an XMLView's content
@return {Promise} resolving to an array with 0..n controls
@private