Ejemplo n.º 1
0
        /// <summary>
        /// Move to  next sibling element
        /// </summary>
        /// <returns>true if the next sibling element was read successfully; false if there are no more sibling elements to read. </returns>
        /// <remarks>Current will move to the end tag of the parent if no more sibling element.</remarks>
        private bool MoveToNextSibling()
        {
            if (_elementState == ElementState.EOF)
            {
                return(false);
            }

            ThrowIfNull();

            if (_elementStack.Count == 0)
            {
                _elementState = ElementState.EOF;
                return(false);
            }

            OpenXmlElement element = _elementStack.Pop();

            // Fix bug #253890, case: the element used to constructor this DOM reader is not root element ( aka. it has parents and siblings. )
            // the stack is empty means we should move to EOF.
            if (_elementStack.Count == 0)
            {
                _elementState = ElementState.EOF;
                return(false);
            }

            element = element.NextSibling();
            if (element != null)
            {
                _elementStack.Push(element);
                if (element is OpenXmlMiscNode)
                {
                    _elementState = ElementState.MiscNode;
                }
                else
                {
                    _elementState = ElementState.Start;
                }

                return(true);
            }
            else
            {
                if (_elementStack.Count > 0)
                {
                    _elementState = ElementState.End;
                }
                else
                {
                    // no more element, EOF
                    _elementState = ElementState.EOF;
                }

                return(false);
            }
        }
        /// <summary>
        /// Removes all of the current element's child elements.
        /// </summary>
        public override void RemoveAllChildren()
        {
            OpenXmlElement element = FirstChild;

            while (element != null)
            {
                OpenXmlElement next = element.NextSibling();

                RemoveChild(element);

                element = next;
            }

            Debug.Assert(_lastChild == null);
        }
 public override IEnumerator <OpenXmlElement> GetEnumerator()
 {
     if (this._container.HasChildren && this._container.FirstChild != null)
     {
         for (OpenXmlElement element = this._container.FirstChild;
              element != null;
              element = element.NextSibling())
         {
             yield return(element);
         }
     }
     else
     {
         yield break;
     }
 }
 public override OpenXmlElement GetItem(int index)
 {
     if (this._container.HasChildren)
     {
         for (OpenXmlElement element = this._container.FirstChild;
              element != null;
              element = element.NextSibling())
         {
             if (index == 0)
             {
                 return(element);
             }
             index--;
         }
     }
     // return null;
     throw new ArgumentOutOfRangeException("index");
 }
        private protected void SetElement <T>(int sequenceNumber, T newChild)
            where T : OpenXmlElement
        {
            switch (OpenXmlCompositeType)
            {
            case OpenXmlCompositeType.Other:
                throw new InvalidOperationException();

            case OpenXmlCompositeType.OneAll:
            {
                T child = GetElement <T>(sequenceNumber);
                if (child != null)
                {
                    // remove the old one
                    RemoveChild(child);
                }

                if (newChild != null)
                {
                    AppendChild(newChild);
                }
            }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?
                break;

            case OpenXmlCompositeType.OneChoice:
            {
                OpenXmlElement child         = FirstChild;
                OpenXmlElement previousChild = null;

                // skip unknown element and MiscNode
                while (child != null && !IsKnownElement(child))
                {
                    previousChild = child;
                    child         = child.NextSibling();
                }

                OpenXmlElement next = null;
                while (child != null)
                {
                    next = child.NextSibling();

                    // remove all exist elements
                    if (IsKnownElement(child))
                    {
                        RemoveChild(child);
                    }

                    child = next;
                }

                if (newChild != null)
                {
                    InsertAfter(newChild, previousChild);
                }
            }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?
                break;

            case OpenXmlCompositeType.OneSequence:
            {
                OpenXmlElement child = FirstChild;
                OpenXmlElement prev  = null;

                while (child != null)
                {
                    if (IsKnownElement(child))
                    {
                        int childSequenceNumber = GetSequenceNumber(child);

                        if (childSequenceNumber == sequenceNumber)
                        {
                            // remove the old one
                            if (child is T)
                            {
                                // insert the new element after the previous.
                                prev = child.PreviousSibling();
                                RemoveChild(child);
                                break;
                            }
                            else
                            {
                                // same tag name, but wrong type, see bug 448241
                                prev = child;
                            }
                        }
                        else if (childSequenceNumber > sequenceNumber)
                        {
                            break;
                        }
                        else
                        {
                            // always insert after the first known element
                            prev = child;

                            // continue search
                        }
                    }

                    // continue search
                    child = child.NextSibling();
                }

                if (newChild != null)
                {
                    InsertAfter(newChild, prev);
                }
            }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?
                break;
            }
        }
        /// <summary>
        /// Gets the child element that has the specified sequence number.
        /// Sequence numbers are generated by a code generator.
        /// </summary>
        /// <param name="sequenceNumber">The sequence number of the element.</param>
        /// <returns>An element that has the specified sequence number. Returns null (Nothing in Visual Basic) if no element is found having the specified sequence number.</returns>
        /// <remarks>
        /// Returns null if there are invalid children.
        /// </remarks>
        internal T GetElement <T>(int sequenceNumber) where T : OpenXmlElement
        {
            T theChild;

            switch (OpenXmlCompositeType)
            {
            case OpenXmlCompositeType.Other:
                throw new InvalidOperationException();

            case OpenXmlCompositeType.OneAll:
                foreach (OpenXmlElement child in ChildElements)
                {
                    // skip unknown element and MiscNode
                    if (OpenXmlElement.IsKnownElement(child))
                    {
                        int childSequenceNumber = GetSequenceNumber(child);
                        if (childSequenceNumber == sequenceNumber)
                        {
                            theChild = child as T;
                            if (theChild != null)
                            {
                                return(theChild);
                            }
                        }
                    }
                }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?

                break;

            case OpenXmlCompositeType.OneChoice:
            {
                OpenXmlElement child = FirstChild;

                // skip unknown element and MiscNode
                while (child != null && !OpenXmlElement.IsKnownElement(child))
                {
                    child = child.NextSibling();
                }

                // There should be only one valide child.
                if (child != null)
                {
                    Debug.Assert(OpenXmlElement.IsKnownElement(child));

                    int childSequenceNumber = GetSequenceNumber(child);
                    if (childSequenceNumber == sequenceNumber)
                    {
                        theChild = child as T;
                        if (theChild != null)
                        {
                            return(theChild);
                        }
                    }
                }
            }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?

                break;

            case OpenXmlCompositeType.OneSequence:
            {
                OpenXmlElement child = FirstChild;

                while (child != null)
                {
                    if (OpenXmlElement.IsKnownElement(child))
                    {
                        int childSequenceNumber = GetSequenceNumber(child);

                        if (childSequenceNumber == sequenceNumber)
                        {
                            theChild = child as T;
                            if (theChild != null)
                            {
                                return(theChild);
                            }
                            else
                            {
                                // same tag name, but wrong type, see bug 448241
                                child = child.NextSibling();
                            }
                        }
                        else if (childSequenceNumber > sequenceNumber)
                        {
                            return(null);
                        }
                        else
                        {
                            child = child.NextSibling();
                        }
                    }
                    else
                    {
                        // skip unknown element and MiscNode
                        child = child.NextSibling();
                    }
                }
            }

                // TODO: should we handle error case?
                //  1: there are more than 1 elements for a type?
                //  2: there are more than 2 elements?
                //  3. there are other elements other than allowed children?

                break;
            }
            return(null);
        }