/**
	 * Extends $param with option children, resolving xml:.... types.
	 *
	 * @param  SimpleXMLElement  $param                  Parameter to extend
	 * @param  bool              $addErrorToXmlAsOption  Should the error be added as an option instead of the options in case of error
	 * @return null|string                               Error message
	 */
	function resolveXmlParamType( SimpleXMLElement $param, $addErrorToXmlAsOption = false )
	{
		$errorMsg		=	null;

		$type			=	$param->attributes( 'type' );

		if ( substr( $type, 0, 4 ) == 'xml:' ) {
			$xmlType	=	substr( $type, 4 );
			if ( $this->_types ) {
				$typeModel	=	$this->_types->getChildByNameAttr( 'type', 'name' , $xmlType );
				// find root type:
				if ( $typeModel ) {
					$root		=	$typeModel;
					$subbasetype =	$root->attributes( 'base' );

					for ( $i = 0; $i < 100; $i++ ) {
						if ( substr( $root->attributes( 'base' ), 0, 4 ) == 'xml:' ) {
							$subbasetype	=	$root->attributes( 'base' );
							$root	=	$this->_types->getChildByNameAttr( 'type', 'name' , substr( $subbasetype, 4 ) );
							if ( ! $root ) {
								$errorMsg	=	"Missing type definition of " . $subbasetype;
								break;
							}
						} else {
							// we found the root and type:
							$type	=	$root->attributes( 'base' );
							break;
						}
					}
					if ( $i >= 99 ) {
						echo 'Error: recursion loop in XML type definition of ' . $typeModel->getName() . ' ' . $typeModel->attributes( 'name' ) . ' type: ' . $typeModel->attributes( 'type' );
						exit;
					}
					$levelModel		=	$typeModel;
					$insertAfter	=	array();
					for ( $i = 0; $i < 100; $i++ ) {
						switch ( $type ) {
							case 'list':
							case 'multilist':
							case 'radio':
							case 'checkbox':
							case 'checkmark':
							case 'published':
							case 'usergroup':
							case 'viewaccesslevel':
							case 'tag':
								$valueType		=	$root->attributes( 'valuetype' );
								$subbasetype	=	$valueType ? $valueType : 'string';

								/*
 								if ( $view ) {
									$valueNode	=	$levelModel->getAnyChildByNameAttr( 'option', 'value', $value );	// recurse in children over optgroups if needed.
									if ( $valueNode ) {
										if ( $htmlFormatting == 'fieldsListArray' ) {
											$result[1]	=	$valueNode->data();
										} else {
											$value	=	$valueNode->data();
										}
									}
								} else {
							 */
								if ( $levelModel->attributes( 'insertbase' ) != 'before' ) {
									foreach ( $levelModel->children() as $option ) {
										/** @var  SimpleXMLElement  $option */
										if ( $option->getName() == 'option' ) {
											$param->addChildWithAttr( 'option', $option->data(), null, $option->attributes() );
										} elseif ( $option->getName() == 'optgroup' ) {
											$paramOptgroup = $param->addChildWithAttr( 'optgroup', $option->data(), null, $option->attributes() );
											// in HTML 4, optgroups can not be nested (w3c)
											foreach ( $option->children() as $optChild ) {
												/** @var  SimpleXMLElement $optChild */
												if ( $optChild->getName() == 'option' ) {
													$paramOptgroup->addChildWithAttr( 'option', $optChild->data(), null, $optChild->attributes() );
												} elseif ( $optChild->getName() == 'data' ) {
													$paramOptgroup->appendChild( $optChild );
												}
											}
										} elseif ( $option->getName() == 'data' ) {
											$param->appendChild( $option );
										}
									}
								} else {
									$insertAfter[]	=	$levelModel;
								}
								break;
							default:
								$errorMsg	=	"Unknown base type " . $type . " in XML";
								break;
						}
						if ( ( $levelModel->attributes( 'name' ) == $typeModel->attributes( 'name' ) ) && ( substr( $levelModel->attributes( 'type' ), 0, 4 ) == 'xml:' ) ) {
							$levelModel	=	$this->_types->getChildByNameAttr( 'type', 'name' , substr( $levelModel->attributes( 'type' ), 4 ) );
						} elseif ( substr( $levelModel->attributes( 'base' ), 0, 4 ) == 'xml:' ) {
							$levelModel	=	$this->_types->getChildByNameAttr( 'type', 'name' , substr( $levelModel->attributes( 'base' ), 4 ) );
						} else {
							break;
						}

					}
					foreach ( $insertAfter as $levelModel ) {
						/** @var  SimpleXMLElement  $levelModel */
						foreach ($levelModel->children() as $option ) {
							/** @var  SimpleXMLElement  $option */
							if ( $option->getName() == 'option' ) {
								$param->addChildWithAttr( 'option', $option->data(), null, $option->attributes() );
							} elseif ( $option->getName() == 'optgroup' ) {
								$paramOptgroup = $param->addChildWithAttr( 'optgroup', $option->data(), null, $option->attributes() );
								foreach ( $option->children() as $optChild ) {
									if ( $optChild->getName() == 'option' ) {
										$paramOptgroup->addChildWithAttr( 'option', $optChild->data(), null, $optChild->attributes() );
									} elseif ( $optChild->getName() == 'data' ) {
										$paramOptgroup->appendChild( $optChild );
									}
								}
							} elseif ( $option->getName() == 'data' ) {
								$param->appendChild( $option );
							}
						}
					}

					$param['type']	=	$type;
					if ( $subbasetype ) {
						$param['base'] = $subbasetype;
					}

				} else {
					$errorMsg	= "Missing type def. for param-type " .  $param->attributes( 'type' );
				}
			} else {
				$errorMsg		=	"No types defined in XML";
			}

			if ( $errorMsg && $addErrorToXmlAsOption ) {
				$param->addChildWithAttr( 'option', $errorMsg, null, array( 'value' => '0') );
			}
		}
		return $errorMsg;
	}