我想使用Inno Setup从XmlDocument中删除注释标记。我的xml大概是这样的。
<?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>
我想用Inno Setup取消注释
<endpoint>
...
</endpoint>
,所以去掉周围的注释标签。
我发现这可以用下面的步骤来完成:
- 获取注释节点的值
- 用步骤1 中的值创建一个新的XmlNode
- 删除注释节点
- 将步骤2中的新节点添加到DOM树
不幸的是,答案中的例子是c#。
if (commentNode != null)
{
XmlReader nodeReader = XmlReader.Create(new StringReader(commentNode.Value));
XmlNode newNode = xdoc.ReadNode(nodeReader);
commentNode.ParentNode.ReplaceChild(newNode, commentNode);
}
到目前为止,我还没有找到如何实现XmlReader与Inno设置。所以,我试了一下。
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
当我将XMLCommentNode的文本值写入日志时,它对我来说似乎是正确的。
[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>
然而,当创建一个新的元素,我得到一个错误消息
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" />
...
'
如何继续并纠正这个错误?
我解决了我的问题,正如Martin Prikryl建议的那样,通过从纯文本文件中删除注释标记<!--
和-->
。我写了以下函数。
XML结构假定为:
<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>
调用的例子:
RemoveCommentTag(ConfigFileName, '//node1/node2/node3/node4', 'attributeNode');
代码: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;