/*************************************************************************** Copyright (c) Microsoft Corporation 2011. This code is licensed using the Microsoft Public License (Ms-PL). The text of the license can be found here: http://www.microsoft.com/resources/sharedsource/licensingbasics/publiclicense.mspx ***************************************************************************/ using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; namespace OpenXmlPowerTools { public static class PtExtensions { public static string StringConcatenate(this IEnumerable source) { StringBuilder sb = new StringBuilder(); foreach (string s in source) sb.Append(s); return sb.ToString(); } public static string StringConcatenate( this IEnumerable source, Func projectionFunc) { return source.Aggregate( new StringBuilder(), (s, i) => s.Append(projectionFunc(i)), s => s.ToString()); } public static IEnumerable Zip( this IEnumerable first, IEnumerable second, Func func) { var ie1 = first.GetEnumerator(); var ie2 = second.GetEnumerator(); while (ie1.MoveNext() && ie2.MoveNext()) yield return func(ie1.Current, ie2.Current); } public static IEnumerable> GroupAdjacent( this IEnumerable source, Func keySelector) { TKey last = default(TKey); bool haveLast = false; List list = new List(); foreach (TSource s in source) { TKey k = keySelector(s); if (haveLast) { if (!k.Equals(last)) { yield return new GroupOfAdjacent(list, last); list = new List(); list.Add(s); last = k; } else { list.Add(s); last = k; } } else { list.Add(s); last = k; haveLast = true; } } if (haveLast) yield return new GroupOfAdjacent(list, last); } private static void InitializeReverseDocumentOrder(XElement element) { XElement prev = null; foreach (XElement e in element.Elements()) { e.AddAnnotation(new ReverseDocumentOrderInfo { PreviousSibling = prev }); prev = e; } } public static IEnumerable ElementsBeforeSelfReverseDocumentOrder( this XElement element) { if (element.Annotation() == null) InitializeReverseDocumentOrder(element.Parent); XElement current = element; while (true) { XElement previousElement = current .Annotation() .PreviousSibling; if (previousElement == null) yield break; yield return previousElement; current = previousElement; } } public static string ToStringNewLineOnAttributes(this XElement element) { XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; settings.NewLineOnAttributes = true; StringBuilder stringBuilder = new StringBuilder(); using (StringWriter stringWriter = new StringWriter(stringBuilder)) using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings)) element.WriteTo(xmlWriter); return stringBuilder.ToString(); } public static IEnumerable DescendantsTrimmed(this XElement element, XName trimName) { return DescendantsTrimmed(element, e => e.Name == trimName); } public static IEnumerable DescendantsTrimmed(this XElement element, Func predicate) { Stack> iteratorStack = new Stack>(); iteratorStack.Push(element.Elements().GetEnumerator()); while (iteratorStack.Count > 0) { while (iteratorStack.Peek().MoveNext()) { XElement currentXElement = iteratorStack.Peek().Current; if (predicate(currentXElement)) { yield return currentXElement; continue; } yield return currentXElement; iteratorStack.Push(currentXElement.Elements().GetEnumerator()); } iteratorStack.Pop(); } } public static IEnumerable Rollup( this IEnumerable source, TResult seed, Func projection) { TResult nextSeed = seed; foreach (TSource src in source) { TResult projectedValue = projection(src, nextSeed); nextSeed = projectedValue; yield return projectedValue; } } public static IEnumerable SequenceAt(this TSource[] source, int index) { int i = index; while (i < source.Length) yield return source[i++]; } } public class ReverseDocumentOrderInfo { public XElement PreviousSibling; } public class GroupOfAdjacent : IEnumerable, IGrouping { public TKey Key { get; set; } private List GroupList { get; set; } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return ((System.Collections.Generic.IEnumerable)this).GetEnumerator(); } System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() { foreach (var s in GroupList) yield return s; } public GroupOfAdjacent(List source, TKey key) { GroupList = source; Key = key; } } public class XEntity : XText { public override void WriteTo(XmlWriter writer) { writer.WriteEntityRef(this.Value); } public XEntity(string value) : base(value) { } } }