Reputation: 49
I am trying to compare two XML files, each put into a different RichTextBox, in VB.NET. The first RichTextBox will have the original XML file, while the second RichTextBox will have an updated XML file. I want to highlight the differences between the two files in the second RichTextBox.
Currently, I simply put each row of text from the original XML file into a List(Of String). I then loop through all the lines of the second RichTextBox and if the List(Of String) does not contain that line, then I know the line was either added (a new line) or was edited, so it has to be highlighted in the second RichTextBox.
This is the code:
Dim sRichTextBox1Lines() As String = RichTextBox1.Lines
Dim sRichTextBox2Lines() As String = RichTextBox2.Lines
Dim sLines As List(Of String) = New List(Of String)
Dim sRichTextBox2Line As String = ""
Dim nIndexStartOfCurrLine As Integer = 0
For i As Integer = 0 To (sRichTextBox1Lines.Length - 1)
sLines.Add(sRichTextBox1Lines(i))
Next
For i As Integer = 0 To (sRichTextBox2Lines.Length)
sRichTextBox2Line = sRichTextBox2Lines(i).ToString
nIndexStartOfCurrLine = RichTextBox2.GetFirstCharIndexFromLine(i)
If (Not sLines.Contains(sRichTextBox2Line)) Then
RichTextBox2.Select(nIndexStartOfCurrLine, sRichTextBox2Lines(i).Length)
RichTextBox2.SelectionColor = Color.White
RichTextBox2.SelectionBackColor = Color.Red
End If
Next
This does the job. However, I was thinking about only highlighting the actual differences, such as a space added, rather than simply highlighting the whole line.
Now this is where I am having issues. I was thinking of going line-by-line and comparing each line to highlight only the difference between the two lines, but there are issues with this approach (e.g. a line was removed, a line was commented out and modified on the next line, a blank line was added, etc.) and the code becomes very convoluted and hard to follow. For example, suppose this is in the first XML file (RichTextBox1):
<add key="Test123A" value="123A"/>
<add key="Test123B" value="123B"/>
<add key="Test123C" value="123C"/>
<add key="Test123D" value="123D"/>
And suppose this is in the second XML file (RichTextBox2):
<add key="Test123A" value="123A"/>
<!--<add key="Test123B" value="123B"/>-->
<add key="Test123B" value="456B" />
<add key="Test123C" value="123C" />
<add key="Test123D" value="123D" />
A line-by-line comparison would be messed up since lines 2 and 3 do not match anything in the original XML file. Also, note that there is now a space after the last quotation marks in the new XML file, which isn't a huge difference (literally a 1-char difference). I was thinking about taking SubStrings but some other parts of the XML file could have the same text, making things complicated.
Perhaps I'm overthinking this but I'm just struggling to find a nice method to highlight only the differences rather than the whole line.
Upvotes: 0
Views: 306
Reputation: 6111
Presumably, the key attribute is a unique value and you only want to compare if the value is different. If that is the case, then load your two XML files into an XDocument object, set the Text property of your RichTextBox controls to their respective XDocument. Then iterate through each <add>
of XDocument A to get the <add>
of XDocument B that share the same key so that you can compare if the value is different. If so, then find the XElement in the RichTextBox to highlight it.
Here is a quick (free-typed untested) example:
'Declare and load the documents
Dim documentA, documentB As New XDocument
documentA.Load("FileA.xml")
documentB.Load("FileB.xml")
'Display the files in the RTB
RichTextBox1.Text = documentA.ToString()
RichTextBox2.Text = documentB.ToString()
'Placeholder variables
Dim addB As XElement
'Iterate through each <add> element
For Each addA As XElement In documentA.Descendants("add")
'Check to make sure that the <add> has a key and value attribute
If addA.HasAttribute("key") AndAlso addB.HasAttribute("value") Then
addB = documentB.Descendants("add").FirstOrDefault(Function(e) e.HasAttribute("key") AndAlso e.Attribute("key") = addA.Attribute("key"))
'Check to make sure that it found an element with the same key and that it also has a value and that the values does not match <addA>'s value
If addB IsNot Nothing AndAlso addB.HasAttribute("value") AndAlso addB.Attribute("value") <> addA.attribute("value") Then
'Get the index of <addB>
Dim index As Integer = RichTextBox2.Find(addB.ToString())
With RichTextBox2
.Select(index, addB.ToString().Length()) 'Select the tag
.SelectionColor = Color.White 'Change the font color
.SelectionBackColor = Color.Read 'Change the background color
End With
End If
End If
Next
Upvotes: 0