// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
namespace Tools.DotNETCommon.XmlHandler
{
///
/// A helper class to handle reading and writing of XML files.
///
public class XmlHandler
{
///
/// Get a good set of default xml writer settings.
///
/// Returns settings that indent with tabs and omit the Xml declaration.
static private XmlWriterSettings GetDefaultWriterSettings()
{
XmlWriterSettings WriterSettings = new XmlWriterSettings();
WriterSettings.CloseOutput = true;
WriterSettings.Indent = true;
WriterSettings.IndentChars = "\t";
WriterSettings.OmitXmlDeclaration = true;
return WriterSettings;
}
///
/// Get a good set of default xml reader settings.
///
/// Returns settings that ignore Xml comments.
static private XmlReaderSettings GetDefaultReaderSettings()
{
XmlReaderSettings ReaderSettings = new XmlReaderSettings();
ReaderSettings.CloseInput = true;
ReaderSettings.IgnoreComments = true;
return ReaderSettings;
}
///
/// A callback for any unknown attributes. Details are spewed to the debug channel.
///
/// Unused.
/// Details about the unknown attribute encountered in the Xml file.
static private void XmlSerializer_UnknownAttribute( object Sender, XmlAttributeEventArgs Event )
{
Debug.WriteLine( " ... unknown XML attribute found '" + Event.Attr.Name + "' at line " + Event.LineNumber + " position " + Event.LinePosition );
}
///
/// A callback for any unknown elements. Details are spewed to the debug channel.
///
/// Unused.
/// Details about the unknown element found in the Xml file.
static private void XmlSerializer_UnknownElement( object Sender, XmlElementEventArgs Event )
{
Debug.WriteLine( " ... unknown XML element found '" + Event.Element.Name + "' at line " + Event.LineNumber + " position " + Event.LinePosition );
}
///
/// A callback for any unknown nodes. Details are spewed to the debug channel.
///
/// Unused.
/// Details about the unknown node found in the Xml file.
static private void XmlSerializer_UnknownNode( object Sender, XmlNodeEventArgs Event )
{
Debug.WriteLine( " ... unknown XML node found '" + Event.Name + "' at line " + Event.LineNumber + " position " + Event.LinePosition );
}
///
/// Returns a string of the contents of a class as Xml.
///
/// The type of the data to convert.
/// The data to serialise.
/// A string with an Xml representation of the data.
/// The default writer settings are tabbed indents and no Xml declaration.
static public string ToXmlString( T Data )
{
XmlSerializer Serialiser = new XmlSerializer( Data.GetType() );
XmlSerializerNamespaces EmptyNameSpace = new XmlSerializerNamespaces();
EmptyNameSpace.Add( "", "http://www.w3.org/2001/XMLSchema" );
using( StringWriter Writer = new StringWriter() )
{
XmlWriter XmlStream = XmlWriter.Create( Writer, GetDefaultWriterSettings() );
Serialiser.Serialize( XmlStream, Data, EmptyNameSpace );
return Writer.ToString();
}
}
///
/// Converts an Xml string to an instantiated class of type T.
///
/// The type of the data we are requesting.
/// A string with an Xml representation of the data.
/// An instance of the type populated with the contents of the Xml string.
static public T FromXmlString( string XmlString )
{
XmlSerializer Serialiser = new XmlSerializer( typeof( T ) );
using( StringReader Reader = new StringReader( XmlString ) )
{
return ( T )Serialiser.Deserialize( Reader );
}
}
///
/// Create and instance of the class, and parse an Xml file into it.
///
/// Path of Xml file to read.
/// Optional settings to control the reading of the Xml file.
/// The type of the class we are attempting to deserialise.
/// An instance of the class with data parsed from the Xml file.
/// This code will never return null, but any field not in the Xml file will be the default value. Unknown attributes,
/// elements, and nodes will be ignored, but output details to the debug channel. The default reader settings ignore comments.
static public T ReadXml( string FileName, XmlReaderSettings ReaderSettings = null ) where T : new()
{
// Create a new default instance of the type
T Instance = new T();
XmlReader XmlStream = null;
try
{
// Use the default reader settings if none are passed in
if( ReaderSettings == null )
{
ReaderSettings = GetDefaultReaderSettings();
}
// Get the xml data stream to read from
XmlStream = XmlReader.Create( FileName, ReaderSettings );
// Creates an instance of the XmlSerializer class so we can read the settings object
XmlSerializer ObjectReader = new XmlSerializer( typeof( T ) );
// Add our callbacks for a malformed xml file
ObjectReader.UnknownNode += new XmlNodeEventHandler( XmlSerializer_UnknownNode );
ObjectReader.UnknownElement += new XmlElementEventHandler( XmlSerializer_UnknownElement );
ObjectReader.UnknownAttribute += new XmlAttributeEventHandler( XmlSerializer_UnknownAttribute );
// Create an object from the xml data
Instance = ( T )ObjectReader.Deserialize( XmlStream );
}
catch( Exception Ex )
{
Debug.WriteLine( Ex.Message );
}
finally
{
if( XmlStream != null )
{
// Done with the file so close it
XmlStream.Close();
}
}
return Instance;
}
///
/// Write an Xml file representing the contents of the class.
///
/// An instance of the class to write.
/// The path of the Xml file to write.
/// Optional default namespace to use.
/// Optional settings to control the writing of the Xml file.
/// The type of the class we wish to write to a file.
/// True if the Xml file was successfully written.
/// The default writer settings are tabbed indents and no Xml declaration.
static public bool WriteXml( T Data, string FileName, string DefaultNameSpace = "", XmlWriterSettings WriterSettings = null )
{
bool bSuccess = true;
XmlWriter XmlStream = null;
try
{
// Ensure the file is writable
FileInfo Info = new FileInfo( FileName );
if( Info.Exists )
{
Info.IsReadOnly = false;
}
// Set the default namespace
XmlSerializerNamespaces EmptyNameSpace = new XmlSerializerNamespaces();
EmptyNameSpace.Add( "", DefaultNameSpace );
// Set the defaults for writing xml files if none is passed in
if( WriterSettings == null )
{
WriterSettings = GetDefaultWriterSettings();
}
XmlStream = XmlWriter.Create( FileName, WriterSettings );
XmlSerializer ObjectWriter = new XmlSerializer( typeof( T ) );
// Add our callbacks for a malformed xml file
ObjectWriter.UnknownNode += new XmlNodeEventHandler( XmlSerializer_UnknownNode );
ObjectWriter.UnknownElement += new XmlElementEventHandler( XmlSerializer_UnknownElement );
ObjectWriter.UnknownAttribute += new XmlAttributeEventHandler( XmlSerializer_UnknownAttribute );
ObjectWriter.Serialize( XmlStream, Data, EmptyNameSpace );
}
catch( Exception Ex )
{
Debug.WriteLine( Ex.Message );
bSuccess = false;
}
finally
{
if( XmlStream != null )
{
// Done with the file so close it
XmlStream.Close();
}
}
return bSuccess;
}
}
}