123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- using System;
- using System.IO;
- using System.Xml;
- using Google.ProtocolBuffers.Descriptors;
- namespace Google.ProtocolBuffers.Serialization
- {
- /// <summary>
- /// Writes a proto buffer to an XML document or fragment. .NET 3.5 users may also
- /// use this class to produce Json by setting the options to support Json and providing
- /// an XmlWriter obtained from <see cref="System.Runtime.Serialization.Json.JsonReaderWriterFactory"/>.
- /// </summary>
- public class XmlFormatWriter : AbstractTextWriter
- {
- public const string DefaultRootElementName = "root";
- private const int NestedArrayFlag = 0x0001;
- private readonly XmlWriter _output;
- private string _rootElementName;
- static XmlWriterSettings DefaultSettings
- {
- get { return new XmlWriterSettings() {CheckCharacters = false, NewLineHandling = NewLineHandling.Entitize}; }
- }
- /// <summary>
- /// Constructs the XmlFormatWriter to write to the given TextWriter
- /// </summary>
- public XmlFormatWriter(TextWriter output) : this(XmlWriter.Create(output, DefaultSettings)) { }
- /// <summary>
- /// Constructs the XmlFormatWriter to write to the given stream
- /// </summary>
- public XmlFormatWriter(Stream output) : this(XmlWriter.Create(output, DefaultSettings)) { }
- /// <summary>
- /// Constructs the XmlFormatWriter to write to the given XmlWriter
- /// </summary>
- public XmlFormatWriter(XmlWriter output)
- {
- _output = output;
- _rootElementName = DefaultRootElementName;
- }
- /// <summary>
- /// Closes the underlying XmlTextWriter
- /// </summary>
- protected override void Dispose(bool disposing)
- {
- if(disposing)
- _output.Close();
- }
- /// <summary>
- /// Gets or sets the default element name to use when using the Merge<TBuilder>()
- /// </summary>
- public string RootElementName
- {
- get { return _rootElementName; }
- set { ThrowHelper.ThrowIfNull(value, "RootElementName"); _rootElementName = value; }
- }
- /// <summary>
- /// Gets or sets the options to use while generating the XML
- /// </summary>
- public XmlWriterOptions Options { get; set; }
- private bool TestOption(XmlWriterOptions option) { return (Options & option) != 0; }
- /// <summary>
- /// Writes a message as an element using the name defined in <see cref="RootElementName"/>
- /// </summary>
- public override void WriteMessage(IMessageLite message)
- { WriteMessage(_rootElementName, message); }
- /// <summary>
- /// Writes a message as an element with the given name
- /// </summary>
- public override void WriteMessage(string elementName, IMessageLite message)
- {
- if (TestOption(XmlWriterOptions.OutputJsonTypes))
- {
- _output.WriteStartElement("root"); // json requires this is the root-element
- _output.WriteAttributeString("type", "object");
- }
- else
- _output.WriteStartElement(elementName);
- message.WriteTo(this);
- _output.WriteEndElement();
- _output.Flush();
- }
- /// <summary>
- /// Writes a message
- /// </summary>
- protected override void WriteMessageOrGroup(string field, IMessageLite message)
- {
- _output.WriteStartElement(field);
- if (TestOption(XmlWriterOptions.OutputJsonTypes))
- _output.WriteAttributeString("type", "object");
- message.WriteTo(this);
- _output.WriteEndElement();
- }
- /// <summary>
- /// Writes a String value
- /// </summary>
- protected override void WriteAsText(string field, string textValue, object typedValue)
- {
- _output.WriteStartElement(field);
- if (TestOption(XmlWriterOptions.OutputJsonTypes))
- {
- if (typedValue is int || typedValue is uint || typedValue is long || typedValue is ulong || typedValue is double || typedValue is float)
- _output.WriteAttributeString("type", "number");
- else if (typedValue is bool)
- _output.WriteAttributeString("type", "boolean");
- }
- _output.WriteString(textValue);
- //Empty strings should not be written as empty elements '<item/>', rather as '<item></item>'
- if (_output.WriteState == WriteState.Element)
- _output.WriteRaw("");
- _output.WriteEndElement();
- }
- /// <summary>
- /// Writes an array of field values
- /// </summary>
- protected override void WriteArray(FieldType fieldType, string field, System.Collections.IEnumerable items)
- {
- //see if it's empty
- System.Collections.IEnumerator eitems = items.GetEnumerator();
- try { if (!eitems.MoveNext()) return; }
- finally
- { if (eitems is IDisposable) ((IDisposable) eitems).Dispose(); }
- if (TestOption(XmlWriterOptions.OutputNestedArrays | XmlWriterOptions.OutputJsonTypes))
- {
- _output.WriteStartElement(field);
- if (TestOption(XmlWriterOptions.OutputJsonTypes))
- _output.WriteAttributeString("type", "array");
- base.WriteArray(fieldType, "item", items);
- _output.WriteEndElement();
- }
- else
- base.WriteArray(fieldType, field, items);
- }
- /// <summary>
- /// Writes a System.Enum by the numeric and textual value
- /// </summary>
- protected override void WriteEnum(string field, int number, string name)
- {
- _output.WriteStartElement(field);
- if (!TestOption(XmlWriterOptions.OutputJsonTypes) && TestOption(XmlWriterOptions.OutputEnumValues))
- _output.WriteAttributeString("value", XmlConvert.ToString(number));
- _output.WriteString(name);
- _output.WriteEndElement();
- }
- }
- }
|