Skip to content

Commit b6be689

Browse files
committed
docs(readme): enhance documentation for in-line comment position generation and update changelog for version 0.2.26
chore(XMLDiff): implement handling of in-line comments for defining position of added elements in diff fix(RunXMLDiff.bat): improve original file path determination logic
1 parent 6bd189a commit b6be689

File tree

4 files changed

+152
-23
lines changed

4 files changed

+152
-23
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ Example:
130130
</diff>
131131
```
132132
133+
#### Defining the position generation for the diff by in-line comment
134+
135+
The `pos` attribute of the `add` usually is set to `after`, taking in account the common logic of how the program is working. But in some cases, you may want to have a diff file with the `pos` attribute set to `before`. Mostly it is useful when it working in conjunction with the vscode - [XMLDiff with VSCode](forVSCode/XMLDIffwithVSCode.md).
136+
From version 0.2.26, you can define the position of the `add` element in the diff file by using an in-line comment in the original XML file. The comment should be placed before the element you want to add and should contain the text `<!-- pos="before" -->`.
137+
133138
### How to apply a diff file
134139
135140
There is a command line help for the `XMLPatch` tool:
@@ -270,6 +275,11 @@ Please be aware - each release archive has an appropriate link to the [VirusTota
270275
271276
## Changelog
272277
278+
### [0.2.26] - 2025-06-16
279+
280+
- Improved:
281+
- Added in-line comments processing for the `add` elements in the modified XML file. It allows to define the position attribute of the `add` element in the diff file.
282+
273283
### [0.2.25] - 2025-03-31
274284
275285
- Fixed:

XMLDiff/Program.cs

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -740,13 +740,47 @@ private static bool CompareElements(
740740
new XAttribute("pos", "prepend")
741741
);
742742
}
743+
// Process each added child, checking for pos=before comments
743744
for (int l = j; l < k; l++)
744745
{
745746
var addedChild = modifiedChildren[l];
746-
addOp.Add(addedChild);
747-
Logger.Info($"[Operation Add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}'.");
747+
748+
// Check if this specific element should use pos=before
749+
if (IsElementPrecededByPosBeforeComment(addedChild))
750+
{
751+
// Create a separate add operation with pos=before for this element
752+
string posBeforeXpath = GenerateXPath(addedChild, pathOptions);
753+
if (!NumericIdsPattern.IsMatch(posBeforeXpath))
754+
{
755+
XElement posBeforeAddOp = new XElement("add", new XAttribute("sel", posBeforeXpath), new XAttribute("pos", "before"));
756+
posBeforeAddOp.Add(addedChild);
757+
DiffRootAddOperation(diffRoot, posBeforeAddOp);
758+
Logger.Info(
759+
$"[Operation Add] Element '{GetElementInfo(addedChild)}' with pos=before to parent '{GetElementInfo(originalElem)}'."
760+
);
761+
}
762+
else
763+
{
764+
// Fall back to the regular add operation if XPath contains numeric IDs
765+
addOp.Add(addedChild);
766+
Logger.Info(
767+
$"[Operation Add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}' (pos=before comment found but using regular add due to numeric XPath)."
768+
);
769+
}
770+
}
771+
else
772+
{
773+
// Use the regular add operation
774+
addOp.Add(addedChild);
775+
Logger.Info($"[Operation Add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}'.");
776+
}
777+
}
778+
779+
// Only add the regular addOp if it has children
780+
if (addOp.HasElements)
781+
{
782+
DiffRootAddOperation(diffRoot, addOp);
748783
}
749-
DiffRootAddOperation(diffRoot, addOp);
750784
j = k;
751785
foundMatch = true;
752786
break;
@@ -800,11 +834,44 @@ private static bool CompareElements(
800834
while (j < modifiedChildren.Count)
801835
{
802836
var addedChild = modifiedChildren[j];
803-
addOp.Add(addedChild);
804-
Logger.Info($"[Operation add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}'.");
837+
838+
// Check if this specific element should use pos=before
839+
if (IsElementPrecededByPosBeforeComment(addedChild))
840+
{
841+
// Create a separate add operation with pos=before for this element
842+
string posBeforeXpath = GenerateXPath(addedChild, pathOptions);
843+
if (!NumericIdsPattern.IsMatch(posBeforeXpath))
844+
{
845+
XElement posBeforeAddOp = new XElement("add", new XAttribute("sel", posBeforeXpath), new XAttribute("pos", "before"));
846+
posBeforeAddOp.Add(addedChild);
847+
DiffRootAddOperation(diffRoot, posBeforeAddOp);
848+
Logger.Info(
849+
$"[Operation add] Element '{GetElementInfo(addedChild)}' with pos=before to parent '{GetElementInfo(originalElem)}'."
850+
);
851+
}
852+
else
853+
{
854+
// Fall back to the regular add operation if XPath contains numeric IDs
855+
addOp.Add(addedChild);
856+
Logger.Info(
857+
$"[Operation add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}' (pos=before comment found but using regular add due to numeric XPath)."
858+
);
859+
}
860+
}
861+
else
862+
{
863+
// Use the regular add operation
864+
addOp.Add(addedChild);
865+
Logger.Info($"[Operation add] Element '{GetElementInfo(addedChild)}' to parent '{GetElementInfo(originalElem)}'.");
866+
}
805867
j++;
806868
}
807-
DiffRootAddOperation(diffRoot, addOp);
869+
870+
// Only add the regular addOp if it has children
871+
if (addOp.HasElements)
872+
{
873+
DiffRootAddOperation(diffRoot, addOp);
874+
}
808875
}
809876
if (checkOnly)
810877
{
@@ -1123,6 +1190,52 @@ private static bool ValidateXsdPath(string? xsdPath)
11231190
}
11241191

11251192
#endregion
1193+
1194+
#region Helper Methods for Comment Detection
1195+
1196+
/// <summary>
1197+
/// Checks if the given element is preceded by an XML comment containing "pos=before"
1198+
/// </summary>
1199+
/// <param name="element">The element to check</param>
1200+
/// <returns>True if the element is preceded by a comment with pos=before, false otherwise</returns>
1201+
private static bool IsElementPrecededByPosBeforeComment(XElement element)
1202+
{
1203+
if (element.Parent == null)
1204+
return false;
1205+
1206+
// Get all nodes from the parent
1207+
var allNodes = element.Parent.Nodes().ToList();
1208+
var elementIndex = allNodes.IndexOf(element);
1209+
1210+
if (elementIndex <= 0)
1211+
return false;
1212+
1213+
// Check the immediate preceding node
1214+
var precedingNode = allNodes[elementIndex - 1];
1215+
1216+
// Check if it's a comment containing "pos=before"
1217+
if (precedingNode is XComment comment)
1218+
{
1219+
string commentText = comment.Value.Trim();
1220+
Logger.Debug($"Found comment preceding element '{element.Name}': '{commentText}'");
1221+
1222+
// Check if comment contains pos=before (case insensitive)
1223+
bool containsPosBeforePattern =
1224+
commentText.Contains("pos=before", StringComparison.OrdinalIgnoreCase)
1225+
|| commentText.Contains("pos=\"before\"", StringComparison.OrdinalIgnoreCase)
1226+
|| commentText.Contains("pos='before'", StringComparison.OrdinalIgnoreCase);
1227+
1228+
if (containsPosBeforePattern)
1229+
{
1230+
Logger.Info($"Element '{element.Name}' is preceded by pos=before comment: '{commentText}'");
1231+
return true;
1232+
}
1233+
}
1234+
1235+
return false;
1236+
}
1237+
1238+
#endregion
11261239
}
11271240

11281241
public class PathOptions

forVSCode/RunXMLDiff.bat

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,12 @@ set "TargetFilePath=%ModifiedFilePath:.modified=%"
2424

2525
REM Determine the original file path
2626
if not "%OriginalFilesPath%"=="" (
27-
set "OriginalFilePath=%OriginalFilesPath%\%Type%\%ModifiedFileName%"
27+
set "OriginalFilePathLocal=%ModifiedFilePath:.modified=.original%"
28+
if not exist "%OriginalFilePathLocal%" (
29+
set "OriginalFilePath=%OriginalFilesPath%\%Type%\%ModifiedFileName%"
30+
) else (
31+
set "OriginalFilePath=%OriginalFilePathLocal"
32+
)
2833
) else (
2934
set "OriginalFilePath=%ModifiedFilePath:.modified=.original%"
3035
)

forVSCode/XMLDIffwithVSCode.md

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,32 +27,33 @@ This document describes how to use XMLDiff with Visual Studio Code.
2727
│ md.original
2828
```
2929
30-
2. You can script creation `*.original` folders, if you will use the `extracted` files folder.
30+
2. You can skip creation `*.original` folders, if you will use the `extracted` files folder.
3131
3. Copy the [RunXMLDiff.bat](/forVSCode/RunXMLDiff.bat) file to the root of your project.
3232
4. Copy the `XMLDiff.exe` file to the `XMLDiffAndPatch` folder in the root of your project.
3333
5. Install the VSCode extension [Run on Save](https://marketplace.visualstudio.com/items?itemName=emeraldwalk.RunOnSave) by [emeraldwalk](https://marketplace.visualstudio.com/publishers/emeraldwalk)
3434
6. Open the settings of the extension by pressing `Ctrl + ,` and search for `runOnSave.commands`
3535
7. Add the following configuration to the settings:
3636
7.1 In case of not to use the "Extracted" files folder, i.e. with `*.original` folders:
3737
38-
```json
39-
"commands": [
40-
{
41-
"match": "\\.modified\\\\.+?\\.xml$",
42-
"cmd": "${workspaceFolder}\\RunXMLDiff.bat ${file} ${workspaceFolder}\\XMLDiffAndPatch\\XMLDiff.exe
43-
}
44-
]
45-
```
38+
```json
39+
"commands": [
40+
{
41+
"match": "\\.modified\\\\.+?\\.xml$",
42+
"cmd": "${workspaceFolder}\\RunXMLDiff.bat ${file} ${workspaceFolder}\\XMLDiffAndPatch\\XMLDiff.exe
43+
}
44+
]
45+
```
4646
4747
7.2. With the `extracted` folder, which is outside the project folder:
4848
49-
```json
50-
"commands": [
51-
{
52-
"match": "\\.modified\\\\.+?\\.xml$",
53-
"cmd": "${workspaceFolder}\\RunXMLDiff.bat ${file} ${workspaceFolder}\\XMLDiffAndPatch\\XMLDiff.exe" ${workspaceFolder}\\..\\extracted"
54-
}
55-
]
49+
```json
50+
"commands": [
51+
{
52+
"match": "\\.modified\\\\.+?\\.xml$",
53+
"cmd": "${workspaceFolder}\\RunXMLDiff.bat ${file} ${workspaceFolder}\\XMLDiffAndPatch\\XMLDiff.exe" ${workspaceFolder}\\..\\extracted"
54+
}
55+
]
56+
```
5657
5758
8. Save the settings and close the settings tab.
5859

0 commit comments

Comments
 (0)