using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Xml; namespace RobvanderWoude { internal class CompareSitemaps { static readonly string progver = "1.00"; static int Main( string[] args ) { int rc = 0; bool quiet = false; bool verbose = false; Stopwatch stopwatch = new Stopwatch( ); #region Command Line Parsing if ( args.Length < 2 || args.Length > 3 ) { return ShowHelp( ); } if ( args.Length == 3 ) { if ( args[2].ToUpper( ) == "/V" ) { verbose = true; } else if ( args[2].ToUpper( ) == "/Q" ) { quiet = true; } else { return ShowHelp( ); } } if ( !File.Exists( args[0] ) ) { return ShowHelp( "File \"{0}\" not found", args[0] ); } if ( !File.Exists( args[1] ) ) { return ShowHelp( "File \"{0}\" not found", args[1] ); } if ( !QuickTestXML( args[0] ) ) { return ShowHelp( "File \"{0}\" is not an XML file", args[0] ); } if ( !QuickTestXML( args[1] ) ) { return ShowHelp( "File \"{0}\" is not an XML file", args[1] ); } #endregion Command Line Parsing if ( verbose ) { stopwatch.Start( ); } #region Open XML XmlReader xml0r = XmlReader.Create( args[0] ); XmlDocument xml0d = new XmlDocument( ); xml0d.Load( xml0r ); XmlReader xml1r= XmlReader.Create( args[1] ); XmlDocument xml1d = new XmlDocument( ); xml1d.Load( xml1r ); int nodecount0 = xml0d.DocumentElement.ChildNodes.Count; int nodecount1 = xml1d.DocumentElement.ChildNodes.Count; if ( nodecount0 != nodecount1 ) { rc = 1; if ( quiet ) { return 1; } } #endregion Open XML if ( verbose ) { Single filesize0 = new FileInfo( args[0] ).Length / 1048576; Single filesize1 = new FileInfo( args[1] ).Length / 1048576; Console.WriteLine( "Files to compare:" ); Console.WriteLine( "=================" ); Console.WriteLine( "{0,5:0.00} MB {1,7} nodes {2}", filesize0, nodecount0, Path.GetFullPath( args[0] ) ); Console.WriteLine( "{0,5:0.00} MB {1,7} nodes {2}", filesize1, nodecount1, Path.GetFullPath( args[1] ) ); Console.WriteLine( ); } #region Read XML SortedList urls = new SortedList( ); SortedList urls0 = new SortedList( ); SortedList urls1 = new SortedList( ); for ( int i = 0; i < nodecount0; i++ ) { string url = xml0d.DocumentElement.ChildNodes[i].ChildNodes[0].InnerText; string lastmod = xml0d.DocumentElement.ChildNodes[i].ChildNodes[1].InnerText; urls[url] = url; urls0[url] = lastmod; } for ( int i = 0; i < nodecount1; i++ ) { string url = xml1d.DocumentElement.ChildNodes[i].ChildNodes[0].InnerText; string lastmod = xml1d.DocumentElement.ChildNodes[i].ChildNodes[1].InnerText; urls[url] = url; urls1[url] = lastmod; } xml0r.Close( ); xml1r.Close( ); #endregion Read XML Console.ForegroundColor = ConsoleColor.Black; Console.BackgroundColor = ConsoleColor.White; int width = Console.WindowWidth; Console.WriteLine( new String( ' ', width - 1 ) ); Console.WriteLine( "Sitemap0: Sitemap1: URL:{0}", new string( ' ', width - 33 ) ); Console.WriteLine( new String( ' ', width - 1 ) ); Console.ResetColor( ); Console.WriteLine( ); ConsoleColor defcol = Console.ForegroundColor; ConsoleColor lm0col = defcol; ConsoleColor lm1col = defcol; ConsoleColor urlcol = defcol; for ( int i = 0; i < urls.Keys.Count; i++ ) { string url = urls.Keys[i]; string lastmod0 = string.Empty; string lastmod1 = string.Empty; if ( urls0.ContainsKey( url ) ) { lastmod0 = urls0[url]; } if ( urls1.ContainsKey( url ) ) { lastmod1 = urls1[url]; } if ( verbose || lastmod0 != lastmod1 ) { if ( lastmod0 != lastmod1 ) { rc = 1; if ( quiet ) { return 1; } if ( string.IsNullOrWhiteSpace( lastmod0 ) ) // url in second sitemap only { lm1col = ConsoleColor.Red; urlcol = ConsoleColor.Cyan; } else if ( string.IsNullOrWhiteSpace( lastmod1 ) ) // url in first sitemap only { lm0col = ConsoleColor.Green; urlcol = ConsoleColor.White; } else if ( string.Compare( lastmod0, lastmod1 ) < 0 ) // url older in first sitemap { lm0col = ConsoleColor.Red; lm1col = ConsoleColor.Green; urlcol = ConsoleColor.DarkYellow; } else // url older in second sitemap { lm0col = ConsoleColor.Green; lm1col = ConsoleColor.Red; urlcol = ConsoleColor.Yellow; } } Console.ForegroundColor = lm0col; Console.Write( "{0,10}\t", lastmod0 ); Console.ForegroundColor = lm1col; Console.Write( "{0,10}\t", lastmod1 ); Console.ForegroundColor = urlcol; Console.WriteLine( url ); lm0col = defcol; lm1col = defcol; urlcol = defcol; } } if ( rc == 0 ) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine( "\nFiles are identical" ); } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine( "\nFiles are different" ); } Console.ResetColor( ); if ( verbose ) { stopwatch.Stop( ); Console.WriteLine( "\nComparison took {0:0.000} seconds", stopwatch.Elapsed.TotalSeconds ); } return rc; } static bool QuickTestXML( string file ) { // Check if the file starts with " 0 ) { System.Collections.Generic.List errargs = new System.Collections.Generic.List( errmsg ); errargs.RemoveAt( 0 ); Console.Error.WriteLine( ); Console.ForegroundColor = ConsoleColor.Red; Console.Error.Write( "ERROR:\t" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( errmsg[0], errargs.ToArray( ) ); Console.ResetColor( ); } #endregion Error Message #region Help Text /* CompareSitemaps.exe, Version 1.00 Compare 2 XML sitemaps and display the differences on screen Usage: CompareSitemaps.exe sitemap1 sitemap2 [ /Q | /V ] Where: sitemap1, sitemap2 XML sitemap files to be compared /Q Quiet mode: no text, return code only /V Verbose mode: show all nodes (default: show differences only) Note: Return code 0 if files are identical, 1 if not, -1 on errors. Written by Rob van der Woude https://www.robvanderwoude.com */ #endregion Help Text #region Display help Console.Error.WriteLine( ); Console.Error.WriteLine( "CompareSitemaps.exe, Version {0}", progver ); Console.Error.WriteLine( "Compare 2 XML sitemaps and display the differences on screen" ); Console.Error.WriteLine( ); Console.Error.Write( "Usage: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.WriteLine( "CompareSitemaps.exe sitemap1 sitemap2 [ /V ]" ); Console.ResetColor( ); Console.Error.WriteLine( ); Console.Error.Write( "Where: " ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( "sitemap1, sitemap2" ); Console.ResetColor( ); Console.Error.WriteLine( " XML sitemap files to be compared" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /Q Q" ); Console.ResetColor( ); Console.Error.WriteLine( "uiet mode: no text, return code only" ); Console.ForegroundColor = ConsoleColor.White; Console.Error.Write( " /V V" ); Console.ResetColor( ); Console.Error.WriteLine( "erbose mode: show all nodes" ); Console.Error.WriteLine( " (default: show differences only)" ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Note: Return code 0 if files are identical, 1 if not, -1 on errors." ); Console.Error.WriteLine( ); Console.Error.WriteLine( "Written by Rob van der Woude" ); Console.Error.WriteLine( "https://www.robvanderwoude.com" ); #endregion Display Help return -1; } #endregion Error handling } }