/// <summary>
        /// Trys to create an OpenXmlElement from the specified namespace URI and local name.
        /// </summary>
        /// <param name="parent">The parent element.</param>
        /// <param name="fileFormat">The specified file format version.</param>
        /// <param name="namespaceUri">The namespace URI of the requested child element.</param>
        /// <param name="localName">The local name of the requested child element.</param>
        /// <returns>A new OpenXmlElement if the parent element can contains a child with the specified namespace and local name. Otherwise, returns null.</returns>
        internal static OpenXmlElement?TryCreateValidChild(this OpenXmlElement parent, FileFormatVersions fileFormat, string namespaceUri, string localName)
        {
            Debug.Assert(parent is OpenXmlCompositeElement);

            var newElement = parent.CreateElement(OpenXmlQualifiedName.Create(namespaceUri, string.Empty, localName));

            if (newElement is OpenXmlUnknownElement || !newElement.IsInVersion(fileFormat))
            {
                return(null);
            }

            return(newElement);
        }
        /// <summary>
        /// Populates the XML into a strong typed DOM tree.
        /// </summary>
        /// <param name="xmlReader">The XmlReader to read the XML content.</param>
        /// <param name="loadMode">Specifies a load mode that is either lazy or full.</param>
        private protected override void Populate(XmlReader xmlReader, OpenXmlLoadMode loadMode)
        {
            LoadAttributes(xmlReader);

            if (!xmlReader.IsEmptyElement)
            {
                xmlReader.Read(); // read this element

                while (!xmlReader.EOF)
                {
                    // O15:#3024890, OpenXmlCompositeElement ignores the Whitespace NodeType.
                    if (xmlReader.NodeType == XmlNodeType.Whitespace)
                    {
                        xmlReader.Skip();
                        continue;
                    }
                    else if (xmlReader.NodeType == XmlNodeType.EndElement)
                    {
                        Debug.Assert(string.Equals(xmlReader.LocalName, LocalName, StringComparison.Ordinal));
                        xmlReader.Skip(); // move to next node
                        break;
                    }

                    OpenXmlElement element = ElementFactory(xmlReader);

                    // set parent before Load( ) call. AlternateContentChoice need parent info on loading.
                    element.Parent = this;

                    bool isACB = element is AlternateContent;
                    if (isACB && element.OpenXmlElementContext is not null)
                    {
                        element.OpenXmlElementContext.ACBlockLevel++;
                    }

                    bool mcContextPushed = false;
                    if (!(element is OpenXmlMiscNode))
                    {
                        // push MC context based on the context of the child element to be loaded
                        mcContextPushed = PushMcContext(xmlReader);
                    }

                    //Process the element according to the MC behavior
                    var action = ElementAction.Normal;
                    if (OpenXmlElementContext is not null && OpenXmlElementContext.MCSettings.ProcessMode != DocumentFormat.OpenXml.Packaging.MarkupCompatibilityProcessMode.NoProcess)
                    {
                        action = OpenXmlElementContext.MCContext.GetElementAction(element, OpenXmlElementContext.MCSettings.TargetFileFormatVersions);
                    }

                    element.Load(xmlReader, loadMode);

                    if (mcContextPushed)
                    {
                        PopMcContext();
                    }

                    if (isACB && element.OpenXmlElementContext is not null)
                    {
                        element.OpenXmlElementContext.ACBlockLevel--;
                    }

                    switch (action)
                    {
                    case ElementAction.Normal:
                    {
                        AddANode(element);
                        break;
                    }

                    case ElementAction.Ignore:
                    {
                        element.Parent = null;
                        continue;
                    }

                    case ElementAction.ProcessContent:
                    {
                        element.Parent = null;
                        while (element.ChildElements.Count > 0)
                        {
                            if (element.FirstChild is not OpenXmlElement node)
                            {
                                break;
                            }

                            node.Remove();
                            var newnode = default(OpenXmlElement);

                            // If node is an UnknowElement, we should try to see whether the parent element can load the node as strong typed element
                            if (node is OpenXmlUnknownElement)
                            {
                                newnode = CreateElement(OpenXmlQualifiedName.Create(node.NamespaceUri, node.Prefix, node.LocalName));
                                if (!(newnode is OpenXmlUnknownElement))
                                {
                                    // The following method will load teh element in MCMode.Full
                                    // since the node is already MC-processed when loading as unknown type, full loading the outerXml is fine
                                    newnode.OuterXml = node.OuterXml;

                                    // unnecessary xmlns attribute will be added, remove it.
                                    RemoveUnnecessaryExtAttr(node, newnode);
                                }
                                else
                                {
                                    newnode = null;
                                }
                            }

                            if (newnode is not null)
                            {
                                AddANode(newnode);
                            }
                            else
                            {
                                //append the original node
                                AddANode(node);
                            }
                        }

                        break;
                    }

                    case ElementAction.ACBlock:
                    {
                        if (element is not AlternateContent acb)
                        {
                            break;
                        }

                        var effectiveNode = OpenXmlElementContext?.MCContext.GetContentFromACBlock(acb, OpenXmlElementContext.MCSettings.TargetFileFormatVersions);
                        if (effectiveNode is null)
                        {
                            break;
                        }

                        element.Parent       = null;
                        effectiveNode.Parent = null;
                        while (effectiveNode.FirstChild is not null)
                        {
                            var node = effectiveNode.FirstChild;
                            node.Remove();
                            AddANode(node);
                            node.CheckMustUnderstandAttr();
                        }

                        break;
                    }
                    }
                }
            }
            else
            {
                xmlReader.Skip();
            }

            // Set raw outer xml to empty to indicate that it passed
            RawOuterXml = string.Empty;
        }