204 lines
4.9 KiB
C#
204 lines
4.9 KiB
C#
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<XMLNode, int> depthMap = new Dictionary<XMLNode, int>();
|
|
Dictionary<int, string> indentMap = new Dictionary<int, string>();
|
|
List<XMLElementNode> stack = new List<XMLElementNode>();
|
|
|
|
|
|
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( "<!DOCTYPE html>" );
|
|
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( "</" + element.fullNodeName + ">" );
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
} |