/// <summary> /// Creates an XML document from a row tree and writes it to a stream using UTF-8 encoding. /// </summary> // If we need to start generating XML on the fly for HTTP responses, it may make sense to create an overload of this method that takes an HttpResponse // object instead of a stream. This new overload would use the HttpResponse.Output property to obtain a TextWriter and then create the XmlWriter on top of // that instead of a stream. The advantage of this approach is that the encoding of the XML would then be determined by ASP.NET, which takes into account // any request headers the client may have sent that pertain to the desired encoding of the response. public static void CreateXmlDocument(MergeRowTree rowTree, MergeFieldNameTree fieldNameTree, Stream destinationStream) { using (var writer = XmlWriter.Create(destinationStream)) { writer.WriteStartDocument(); writeRowTreeXmlElement(rowTree, fieldNameTree, writer); writer.WriteEndDocument(); } }
private static void writeRowTreeXmlElement(MergeRowTree rowTree, MergeFieldNameTree fieldNameTree, XmlWriter writer) { writer.WriteStartElement(rowTree.NodeName); foreach (var row in rowTree.Rows) { writer.WriteStartElement(rowTree.XmlRowElementName); foreach (var fieldName in fieldNameTree.FieldNames) { var mergeValue = row.Values.SingleOrDefault(i => i.Name == fieldName); if (mergeValue == null) { // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called. throw new ApplicationException("Merge field " + fieldName + " is invalid."); } writer.WriteStartElement(mergeValue.Name); if (mergeValue is MergeValue <string> ) { writer.WriteValue((mergeValue as MergeValue <string>).Evaluate(false)); } else { // Use ApplicationException instead of MailMergingException because the field names can easily be validated before this method is called. throw new ApplicationException("Merge field " + mergeValue.Name + " evaluates to an unsupported type."); } writer.WriteEndElement(); } foreach (var childNameAndFieldNameTree in fieldNameTree.ChildNamesAndChildren) { var childRowTree = row.Children.SingleOrDefault(i => i.NodeName == childNameAndFieldNameTree.Item1); if (childRowTree == null) { // Use ApplicationException instead of MailMergingException because the child names can easily be validated before this method is called. throw new ApplicationException("Child " + childNameAndFieldNameTree.Item1 + " is invalid."); } writeRowTreeXmlElement(childRowTree, childNameAndFieldNameTree.Item2, writer); } writer.WriteEndElement(); } writer.WriteEndElement(); }