Reputation: 149
I would like to remove a comment tag from a XmlDocument using Inno Setup. My xml looks approximately like this.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<services>
<service name="AuthenticationService">
<!--
<endpoint contract="System.Web.ApplicationServices.AuthenticationService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
-->
</service>
</services>
</system.serviceModel>
</configuration>
I would like to uncomment using Inno Setup the section
<endpoint>
...
</endpoint>
, so remove the comment tags around it.
I found from here that this could be done using the following procedure:
Unfortunately the example in the answer is in C#.
if (commentNode != null)
{
XmlReader nodeReader = XmlReader.Create(new StringReader(commentNode.Value));
XmlNode newNode = xdoc.ReadNode(nodeReader);
commentNode.ParentNode.ReplaceChild(newNode, commentNode);
}
So far I haven't found how to implement XmlReader with Inno Setup. So, I tried this.
APath := '//configuration/system.serviceModel/services/service/comment()';
XMLCommentNode := XMLDoc.selectSingleNode(APath);
if Not (IDispatch(XMLCommentNode) = nil) then
begin
Log('Remove comment tag ' + APath + ' value is: ' + XMLCommentNode.Text);
newNode := XMLDoc.createElement(XMLCommentNode.Text);
XMLCommentNode.ParentNode.ReplaceChild(newNode, XMLCommentNode);
end
The text value of XMLCommentNode seems correct to me when I write it to log.
[08.59.44,190] Remove comment tag //configuration/system.serviceModel/services/service/comment() value is:
<endpoint contract="System.Web.ApplicationServices.AuthenticationService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
However, when creating a new element from that I get an error message
Internal error: Expression error 'Runtime error (at 20:2651):
msxml3.dll: This name may not contain the '
' character:
-->
<-- <endpoint contract="System.Web.ApplicationServices.AuthenticationService">
<identity>
<dns value="localhost" />
...
'
How proceed and correct this error?
Upvotes: 2
Views: 307
Reputation: 149
I solved my problem, as Martin Prikryl suggested, by removing comment tags <!--
and -->
from plain text file. For that I wrote the following function.
XML structure is assumed to be like:
<node1>
<node2>
<node3>
<node4 name="AuthenticationService">
<!-- This comment should be removed
<attributeNode some_data="some data">
<subnode>
<specifier value="special" />
</subnode>
</attributeNode>
-->
</node4>
</node3>
</node2>
</node1>
Call example:
RemoveCommentTag(ConfigFileName, '//node1/node2/node3/node4', 'attributeNode');
Code:
function RemoveCommentTag(const FileName, TagPath, Attribute: string): Boolean;
var
I: Integer;
Line: string;
AttributeLine: string;
TagPos, AttributePos, CommentPos: Integer;
FileLines: TStringList;
TagPaths: TArrayOfString;
Tag: string;
TagCntr: Integer;
Found: boolean;
begin
Result := False;
TagPaths:= StrSplit(TagPath, '/');
FileLines := TStringList.Create;
try
//Tag := TagName + '=';
FileLines.LoadFromFile(FileName);
I := 0;
for TagCntr := 0 to GetArrayLength(TagPaths) -1 do
begin
Tag := TagPaths[TagCntr];
if Tag <> '' then
begin
// Search for Tag
Found := false;
while (I < FileLines.Count) and not Found do
begin
Line := FileLines[I];
TagPos := Pos(Tag, Line);
if TagPos > 0 then
Found := True;
I := I + 1;
end;
end;
end;
// After this I should have the line number where the searched section begins.
// Then search for comment opening tag '<!--'
// Check, that the comment is before correct attribute
Found := false;
while (I < FileLines.Count) and not Found do
begin
Line := FileLines[I];
// Check also, that there really is comment inside this tag.
TagPos := Pos('/'+Tag, Line);
if TagPos > 0 then
begin
// Malformed XML file. There is no comment inside this tag.
// We can exit function.
exit;
end;
CommentPos := Pos('<!--', Line);
if CommentPos > 0 then
begin
AttributeLine := FileLines[I+1];
AttributePos := Pos(Attribute, AttributeLine);
if AttributePos > 0 then
Found := True
end
else
I := I + 1;
end;
// Correct comment tag <!-- should now be on line number I
// Delete whole line from the beginning of comment tag or
// add comment ending tag to the end of this line
//Delete(Line, TagPos + Length('<!--'), MaxInt);
//Delete(Line, TagPos, MaxInt);
// Check that there is no comment ending tag on the same line.
// Otherwise add comment ending tag.
CommentPos := Pos('-->', Line);
if (I < FileLines.Count) and (CommentPos = 0) then
begin
Line := Line + ' -->';
FileLines[I] := Line;
FileLines.SaveToFile(FileName);
end;
// Then continue from next line and search for comment ending tag -->
I := I + 1;
Found := false;
while (I < FileLines.Count) and not Found do
begin
Line := FileLines[I];
// Check also, that there really is comment inside this tag.
TagPos := Pos('/'+Tag, Line);
if TagPos > 0 then
begin
// There is no comment ending tag inside this tag. We can exit function.
// Probably script has already been run.
exit;
end;
CommentPos := Pos('-->', Line);
if CommentPos > 0 then
Found := True
else
I := I + 1;
end;
// <!-- should be now on line number I
// Delete it to the end of the line
if I < FileLines.Count then
begin
Delete(Line, CommentPos, MaxInt);
FileLines[I] := Line;
FileLines.SaveToFile(FileName);
end;
finally
FileLines.Free;
end;
end;
Upvotes: 1