Skip to content

Commit 1abd530

Browse files
committed
fix(XMLDiff): return back the Indent detection and write
fix(XMLPatch): return back the Indent detection and write fix(XMLPatch): default add pos now is append
1 parent f701cda commit 1abd530

File tree

2 files changed

+60
-37
lines changed

2 files changed

+60
-37
lines changed

XMLDiff/Program.cs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ private static void ProcessSingleFile(string originalXmlPath, string modifiedXml
210210
XDocument originalDoc = XDocument.Load(originalXmlPath);
211211
Logger.Info($"Parsed original XML: {originalXmlPath}");
212212

213+
int indent = DetectIndentation(originalXmlPath);
214+
Logger.Info($"Detected indentation: {indent}");
215+
213216
XDocument modifiedDoc = XDocument.Load(modifiedXmlPath);
214217
Logger.Info($"Parsed modified XML: {modifiedXmlPath}");
215218

@@ -230,7 +233,16 @@ private static void ProcessSingleFile(string originalXmlPath, string modifiedXml
230233
XDocument diffDoc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), diffRoot);
231234

232235

233-
diffDoc.Save(diffXmlPath);
236+
var settings = new XmlWriterSettings
237+
{
238+
Indent = true,
239+
IndentChars = new string(' ', indent)
240+
};
241+
using (var writer = XmlWriter.Create(diffXmlPath, settings))
242+
{
243+
diffDoc.Save(writer);
244+
}
245+
234246
if (diffReaderSettings != null)
235247
{
236248
Logger.Info($"Diff XML written to {diffXmlPath} and will be validated");
@@ -296,7 +308,7 @@ private static void ProcessDirectories(string originalDir, string modifiedDir, s
296308

297309
#region Indentation Detection
298310

299-
private static string DetectIndentation(string xmlPath)
311+
private static int DetectIndentation(string xmlPath)
300312
{
301313
var indentationLevels = new HashSet<string>();
302314
var indentPattern = new Regex(@"^(\s+)<");
@@ -311,7 +323,7 @@ private static string DetectIndentation(string xmlPath)
311323
}
312324

313325
if (indentationLevels.Count == 0)
314-
return " "; // Default to four spaces
326+
return 4;
315327

316328
var sortedIndents = indentationLevels.OrderBy(s => s.Length).ToList();
317329

@@ -321,9 +333,7 @@ private static string DetectIndentation(string xmlPath)
321333

322334
int perLevelIndentLen = differences.Any() ? differences.Min() : (sortedIndents[0].Length);
323335

324-
var perLevelIndent = sortedIndents.FirstOrDefault(s => s.Length == perLevelIndentLen) ?? " ";
325-
326-
return perLevelIndent;
336+
return perLevelIndentLen;
327337
}
328338

329339
#endregion
@@ -719,15 +729,6 @@ private static XmlReaderSettings CreateXmlReaderSettings(string xsdPath)
719729
}
720730

721731

722-
#endregion
723-
724-
#region Utility Functions
725-
726-
private static string ConsoleEscape(string str)
727-
{
728-
return str.Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r");
729-
}
730-
731732
#endregion
732733
}
733734

XMLPatch/Program.cs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -206,39 +206,45 @@ private static void ProcessSingleFile(string originalXmlPath, string diffXmlPath
206206
XDocument originalDoc = XDocument.Load(originalXmlPath);
207207
Logger.Info($"Parsed original XML: {originalXmlPath}");
208208

209+
int indent = DetectIndentation(originalXmlPath);
210+
Logger.Info($"Detected indentation: {indent}");
211+
209212
XDocument diffDoc = XDocument.Load(diffXmlPath);
210213
Logger.Info($"Parsed diff XML: {diffXmlPath}");
211214

212-
XElement diffRoot = diffDoc.Root;
215+
XElement diffRoot = diffDoc.Root ?? throw new InvalidOperationException("diffDoc.Root is null");
216+
217+
XElement originalRoot = originalDoc.Root ?? throw new InvalidOperationException("originalDoc.Root is null");
213218

214219
foreach (var operation in diffRoot.Elements())
215220
{
216221
switch (operation.Name.LocalName)
217222
{
218223
case "add":
219-
ApplyAdd(operation, originalDoc.Root);
224+
ApplyAdd(operation, originalRoot);
220225
break;
221226
case "replace":
222-
ApplyReplace(operation, originalDoc.Root);
227+
ApplyReplace(operation, originalRoot);
223228
break;
224229
case "remove":
225-
ApplyRemove(operation, originalDoc.Root);
230+
ApplyRemove(operation, originalRoot);
226231
break;
227232
default:
228233
Logger.Warn($"Unknown operation: {operation.Name}. Skipping.");
229234
break;
230235
}
231236
}
232237

233-
// Ensure output directory exists
234-
string outputDir = Path.GetDirectoryName(outputXmlPath);
235-
if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
238+
var settings = new XmlWriterSettings
239+
{
240+
Indent = true,
241+
IndentChars = new string(' ', indent)
242+
};
243+
using (var writer = XmlWriter.Create(diffXmlPath, settings))
236244
{
237-
Directory.CreateDirectory(outputDir);
238-
Logger.Info($"Created output directory: {outputDir}");
245+
originalDoc.Save(writer);
239246
}
240247

241-
originalDoc.Save(outputXmlPath);
242248
Logger.Info($"Patched XML successfully written to '{outputXmlPath}'.");
243249
}
244250
catch (Exception ex)
@@ -270,7 +276,7 @@ private static void ProcessDirectories(string originalDir, string diffDir, strin
270276

271277
#region Indentation Detection
272278

273-
private static string DetectIndentation(string xmlPath)
279+
private static int DetectIndentation(string xmlPath)
274280
{
275281
var indentationLevels = new HashSet<string>();
276282
var indentPattern = new Regex(@"^(\s+)<");
@@ -285,14 +291,13 @@ private static string DetectIndentation(string xmlPath)
285291
}
286292

287293
if (indentationLevels.Count == 0)
288-
return " "; // Default to four spaces
294+
return 4; // Default to four spaces
289295

290296
var sortedIndents = indentationLevels.OrderBy(s => s.Length).ToList();
291297
var indentLengths = sortedIndents.Where(s => s.Length > 0).Select(s => s.Length).OrderBy(n => n).ToList();
292298
var differences = indentLengths.Skip(1).Select((len, idx) => len - indentLengths[idx]).Where(diff => diff > 0).ToList();
293299
int perLevelIndentLen = differences.Any() ? differences.Min() : sortedIndents[0].Length;
294-
var perLevelIndent = sortedIndents.FirstOrDefault(s => s.Length == perLevelIndentLen) ?? " ";
295-
return perLevelIndent;
300+
return perLevelIndentLen;
296301
}
297302

298303
#endregion
@@ -301,8 +306,10 @@ private static string DetectIndentation(string xmlPath)
301306

302307
private static void ApplyAdd(XElement addElement, XElement originalRoot)
303308
{
304-
string sel = addElement.Attribute("sel")?.Value;
305-
string pos = addElement.Attribute("pos")?.Value ?? "after";
309+
string sel = addElement.Attribute("sel")?.Value ?? throw new ArgumentException("The 'sel' attribute is required.");
310+
string pos = addElement.Attribute("pos")?.Value ?? "append";
311+
312+
Logger.Debug($"Applying add operation: {sel} at {pos}");
306313

307314
var newElements = addElement.Elements();
308315

@@ -323,18 +330,23 @@ private static void ApplyAdd(XElement addElement, XElement originalRoot)
323330
if (pos == "before")
324331
{
325332
target.AddBeforeSelf(cloned);
326-
Logger.Info($"Added new element '{cloned.Name}' before '{target.Name}' in '{target.Parent.Name}'.");
333+
Logger.Info($"Added new element '{cloned.Name}' before '{target.Name}' in '{target.Parent?.Name}'.");
327334
}
328335
else if (pos == "after")
329336
{
330337
target.AddAfterSelf(cloned);
331-
Logger.Info($"Added new element '{cloned.Name}' after '{target.Name}' in '{target.Parent.Name}'.");
338+
Logger.Info($"Added new element '{cloned.Name}' after '{target.Name}' in '{target.Parent?.Name}'.");
332339
}
333340
else if (pos == "prepend")
334341
{
335342
target.AddFirst(cloned);
336343
Logger.Info($"Prepended new element '{cloned.Name}' to '{target.Name}'.");
337344
}
345+
else if (pos == "append")
346+
{
347+
target.Add(cloned);
348+
Logger.Info($"Appended new element '{cloned.Name}' to '{target.Name}'.");
349+
}
338350
else
339351
{
340352
Logger.Warn($"Unknown position: {pos}. Skipping insertion.");
@@ -346,7 +358,7 @@ private static void ApplyAdd(XElement addElement, XElement originalRoot)
346358

347359
private static void ApplyReplace(XElement replaceElement, XElement originalRoot)
348360
{
349-
string sel = replaceElement.Attribute("sel")?.Value;
361+
string? sel = replaceElement.Attribute("sel")?.Value;
350362
if (sel == null)
351363
{
352364
Logger.Warn("Replace operation missing 'sel' attribute.");
@@ -394,7 +406,7 @@ private static void ApplyReplace(XElement replaceElement, XElement originalRoot)
394406

395407
private static void ApplyRemove(XElement removeElement, XElement originalRoot)
396408
{
397-
string sel = removeElement.Attribute("sel")?.Value;
409+
string? sel = removeElement.Attribute("sel")?.Value;
398410
if (sel == null)
399411
{
400412
Logger.Warn("Remove operation missing 'sel' attribute.");
@@ -412,13 +424,23 @@ private static void ApplyRemove(XElement removeElement, XElement originalRoot)
412424
{
413425
if (targetObj is XElement target)
414426
{
415-
XElement parent = target.Parent;
427+
XElement? parent = target.Parent;
428+
if (parent == null)
429+
{
430+
Logger.Warn($"Element '{target.Name}' has no parent. Cannot remove.");
431+
continue;
432+
}
416433
target.Remove();
417434
Logger.Debug($"Removed element '{target.Name}' from '{parent.Name}'.");
418435
}
419436
else if (targetObj is XAttribute attr)
420437
{
421-
XElement parent = attr.Parent;
438+
XElement? parent = attr.Parent;
439+
if (parent == null)
440+
{
441+
Logger.Warn($"Attribute '{attr.Name}' has no parent. Cannot remove.");
442+
continue;
443+
}
422444
attr.Remove();
423445
Logger.Debug($"Removed attribute '{attr.Name}' from '{parent.Name}'.");
424446
}

0 commit comments

Comments
 (0)