using System.Collections; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Text; namespace Rokojori { public class XMLSerializer { StringBuilder sb = new StringBuilder(); XMLWalker walker = new XMLWalker(); string indent = " "; Dictionary depthMap = new Dictionary(); Dictionary indentMap = new Dictionary(); List stack = new List(); public static string Escape( string rawText ) { rawText = RegexUtility.Replace( rawText, "&", "&" ); rawText = RegexUtility.Replace( rawText, "<", "<" ); rawText = RegexUtility.Replace( rawText, ">", ">" ); rawText = RegexUtility.Replace( rawText, "\'", "'" ); rawText = RegexUtility.Replace( rawText, "\"", """ ); return rawText; } public static string Unescape( string escapedText ) { escapedText = RegexUtility.Replace( escapedText, "&", "&" ); escapedText = RegexUtility.Replace( escapedText, "<", "<" ); escapedText = RegexUtility.Replace( escapedText, ">,", ">" ); escapedText = RegexUtility.Replace( escapedText, "'", "\'" ); escapedText = RegexUtility.Replace( escapedText, ""","\"" ); return escapedText; } public string SerializeXMLNode( XMLNode node ) { walker.DepthIterate( node, ( n, d ) => { var depth = GetDepth( n ); ClosePreviousElements( depth ); var element = n as XMLElementNode; RJLog.Log( "Processing:", n ); if ( element != null ) { sb.Append( "\n" ); sb.Append( GetIndent( depth ) ); sb.Append( "<" + element.fullNodeName ); for ( int i = 0; i < element.numAttributes; i++ ) { var attribute = element.GetAttributeAt( i ); sb.Append( " " ); sb.Append( attribute.fullName ); sb.Append( "=\"" ); sb.Append( Escape( attribute.value ) ); sb.Append( "\""); } sb.Append( ">" ); stack.Add( element ); } else { if ( n.parentElement != null && ( HTMLElementName.style.Selects( n.parentElement ) || HTMLElementName.script.Selects( n.parentElement ) ) ) { sb.Append( n.nodeValue ); } else { var nodeValue = n.nodeValue; if ( nodeValue != null ) { if ( XMLNode.NodeType.Text == n.nodeType ) { sb.Append( Escape( n.nodeValue ) ); } else { sb.Append( n.nodeValue ); } } } } }, false, depthMap ); ClosePreviousElements( -1 ); return sb.ToString(); } public string SerializeHtml( XMLNode node ) { sb.Append( "" ); return SerializeXMLNode( node ); } string GetIndent( int depth ) { if ( indentMap.ContainsKey( depth ) ) { return indentMap[ depth ]; } if ( depth == 0 ) { indentMap[ 0 ] = ""; return ""; } if ( indentMap.ContainsKey( depth - 1 ) ) { var smallerIndent = indentMap[ depth -1 ]; indentMap[ depth ] = smallerIndent + indent; return indentMap[ depth ]; } var sb = new StringBuilder(); for ( int i = 0; i < depth; i++ ) { sb.Append( indent ); } indentMap[ depth ] = sb.ToString(); return indentMap[ depth ]; } int GetDepth( XMLNode n ) { return walker.GetDepth( n, depthMap ); } void ClosePreviousElements( int currentDepth ) { for ( int i = stack.Count - 1; i >= 0; i-- ) { var stackDepth = GetDepth( stack[ i ] ); if ( stackDepth >= currentDepth ) { var element = stack[ i ]; stack.RemoveAt( i ); if ( NeedsLineBreak( element ) ) { sb.Append( "\n" ); sb.Append( GetIndent( stackDepth ) ); } sb.Append( "" ); } else { i = -1; } } } bool NeedsLineBreak( XMLElementNode elementNode ) { if ( elementNode.numChildren == 0 || elementNode.HasOnlyTextNodes() && ! ( HTMLElementName.script.Selects( elementNode ) || HTMLElementName.style.Selects( elementNode ) ) ) { return false; } return true; } } }