/// <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); }