internal 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 && !OpenXmlElement.IsKnownElement(child)) { previousChild = child; child = child.NextSibling(); } OpenXmlElement next = null; while (child != null) { next = child.NextSibling(); // remove all exist elements if (OpenXmlElement.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 (OpenXmlElement.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); }