/// <summary>Find or create a schema node if <c>createNodes</c> is true.</summary>
        /// <param name="tree">the root of the xmp tree.</param>
        /// <param name="namespaceUri">a namespace</param>
        /// <param name="suggestedPrefix">If a prefix is suggested, the namespace is allowed to be registered.</param>
        /// <param name="createNodes">
        /// a flag indicating if the node shall be created if not found.
        /// <em>Note:</em> The namespace must be registered prior to this call.
        /// </param>
        /// <returns>
        /// Returns the schema node if found, <c>null</c> otherwise.
        /// Note: If <c>createNodes</c> is <c>true</c>, it is <b>always</b>
        /// returned a valid node.
        /// </returns>
        /// <exception cref="XmpException">
        /// An exception is only thrown if an error occurred, not if a
        /// node was not found.
        /// </exception>
        internal static XmpNode FindSchemaNode(XmpNode tree, string namespaceUri, string suggestedPrefix, bool createNodes)
        {
            Debug.Assert(tree.Parent == null);
            // make sure that its the root
            var schemaNode = tree.FindChildByName(namespaceUri);

            if (schemaNode == null && createNodes)
            {
                var po = new PropertyOptions {
                    IsSchemaNode = true
                };
                schemaNode = new XmpNode(namespaceUri, po)
                {
                    IsImplicit = true
                };
                // only previously registered schema namespaces are allowed in the XMP tree.
                var prefix = XmpMetaFactory.SchemaRegistry.GetNamespacePrefix(namespaceUri);
                if (prefix == null)
                {
                    if (!string.IsNullOrEmpty(suggestedPrefix))
                    {
                        prefix = XmpMetaFactory.SchemaRegistry.RegisterNamespace(namespaceUri, suggestedPrefix);
                    }
                    else
                    {
                        throw new XmpException("Unregistered schema namespace URI", XmpErrorCode.BadSchema);
                    }
                }
                schemaNode.Value = prefix;
                tree.AddChild(schemaNode);
            }
            return(schemaNode);
        }
        /// <summary>Find or create a child node under a given parent node.</summary>
        /// <remarks>
        /// Find or create a child node under a given parent node. If the parent node is no
        /// Returns the found or created child node.
        /// </remarks>
        /// <param name="parent">the parent node</param>
        /// <param name="childName">the node name to find</param>
        /// <param name="createNodes">flag, if new nodes shall be created.</param>
        /// <returns>Returns the found or created node or <c>null</c>.</returns>
        /// <exception cref="XmpException">Thrown if</exception>
        internal static XmpNode FindChildNode(XmpNode parent, string childName, bool createNodes)
        {
            if (!parent.Options.IsSchemaNode && !parent.Options.IsStruct)
            {
                if (!parent.IsImplicit)
                {
                    throw new XmpException("Named children only allowed for schemas and structs", XmpErrorCode.BadXPath);
                }
                if (parent.Options.IsArray)
                {
                    throw new XmpException("Named children not allowed for arrays", XmpErrorCode.BadXPath);
                }
                if (createNodes)
                {
                    parent.Options.IsStruct = true;
                }
            }
            var childNode = parent.FindChildByName(childName);

            if (childNode == null && createNodes)
            {
                var options = new PropertyOptions();
                childNode = new XmpNode(childName, options)
                {
                    IsImplicit = true
                };
                parent.AddChild(childNode);
            }
            Debug.Assert(childNode != null || !createNodes);
            return(childNode);
        }