/// <summary>Visit all of the top level nodes looking for aliases.</summary>
        /// <remarks>
        /// Visit all of the top level nodes looking for aliases. If there is
        /// no base, transplant the alias subtree. If there is a base and strict
        /// aliasing is on, make sure the alias and base subtrees match.
        /// </remarks>
        /// <param name="tree">the root of the metadata tree</param>
        /// <param name="options">th parsing options</param>
        /// <exception cref="Com.Adobe.Xmp.XMPException">Forwards XMP errors</exception>
        private static void MoveExplicitAliases(XMPNode tree, ParseOptions options)
        {
            if (!tree.GetHasAliases())
            {
                return;
            }
            tree.SetHasAliases(false);
            bool strictAliasing = options.GetStrictAliasing();

            for (Iterator schemaIt = tree.GetUnmodifiableChildren().Iterator(); schemaIt.HasNext();)
            {
                XMPNode currSchema = (XMPNode)schemaIt.Next();
                if (!currSchema.GetHasAliases())
                {
                    continue;
                }
                for (Iterator propertyIt = currSchema.IterateChildren(); propertyIt.HasNext();)
                {
                    XMPNode currProp = (XMPNode)propertyIt.Next();
                    if (!currProp.IsAlias())
                    {
                        continue;
                    }
                    currProp.SetAlias(false);
                    // Find the base path, look for the base schema and root node.
                    XMPAliasInfo info = XMPMetaFactory.GetSchemaRegistry().FindAlias(currProp.GetName());
                    if (info != null)
                    {
                        // find or create schema
                        XMPNode baseSchema = XMPNodeUtils.FindSchemaNode(tree, info.GetNamespace(), null, true);
                        baseSchema.SetImplicit(false);
                        XMPNode baseNode = XMPNodeUtils.FindChildNode(baseSchema, info.GetPrefix() + info.GetPropName(), false);
                        if (baseNode == null)
                        {
                            if (info.GetAliasForm().IsSimple())
                            {
                                // A top-to-top alias, transplant the property.
                                // change the alias property name to the base name
                                string qname = info.GetPrefix() + info.GetPropName();
                                currProp.SetName(qname);
                                baseSchema.AddChild(currProp);
                                // remove the alias property
                                propertyIt.Remove();
                            }
                            else
                            {
                                // An alias to an array item,
                                // create the array and transplant the property.
                                baseNode = new XMPNode(info.GetPrefix() + info.GetPropName(), info.GetAliasForm().ToPropertyOptions());
                                baseSchema.AddChild(baseNode);
                                TransplantArrayItemAlias(propertyIt, currProp, baseNode);
                            }
                        }
                        else
                        {
                            if (info.GetAliasForm().IsSimple())
                            {
                                // The base node does exist and this is a top-to-top alias.
                                // Check for conflicts if strict aliasing is on.
                                // Remove and delete the alias subtree.
                                if (strictAliasing)
                                {
                                    CompareAliasedSubtrees(currProp, baseNode, true);
                                }
                                propertyIt.Remove();
                            }
                            else
                            {
                                // This is an alias to an array item and the array exists.
                                // Look for the aliased item.
                                // Then transplant or check & delete as appropriate.
                                XMPNode itemNode = null;
                                if (info.GetAliasForm().IsArrayAltText())
                                {
                                    int xdIndex = XMPNodeUtils.LookupLanguageItem(baseNode, XMPConstConstants.XDefault);
                                    if (xdIndex != -1)
                                    {
                                        itemNode = baseNode.GetChild(xdIndex);
                                    }
                                }
                                else
                                {
                                    if (baseNode.HasChildren())
                                    {
                                        itemNode = baseNode.GetChild(1);
                                    }
                                }
                                if (itemNode == null)
                                {
                                    TransplantArrayItemAlias(propertyIt, currProp, baseNode);
                                }
                                else
                                {
                                    if (strictAliasing)
                                    {
                                        CompareAliasedSubtrees(currProp, itemNode, true);
                                    }
                                    propertyIt.Remove();
                                }
                            }
                        }
                    }
                }
                currSchema.SetHasAliases(false);
            }
        }