【问题标题】:How to remove a comment tag from XmlDocument with Inno Setup如何使用 Inno Setup 从 XmlDocument 中删除注释标记
【发布时间】:2021-11-25 11:10:00
【问题描述】:

我想使用 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>

,所以删除它周围的评论标签。

我从here 发现这可以使用以下过程完成:

  1. 获取评论节点的值
  2. 使用步骤 1 中的值创建一个新的 XmlNode
  3. 删除评论节点
  4. 将步骤 2 中的新节点添加到 DOM 树中

不幸的是,答案中的示例是用 C# 编写的。

if (commentNode != null)
{
  XmlReader nodeReader = XmlReader.Create(new StringReader(commentNode.Value));
  XmlNode newNode = xdoc.ReadNode(nodeReader);
  commentNode.ParentNode.ReplaceChild(newNode, commentNode);
}

到目前为止,我还没有找到如何使用 Inno Setup 实现 XmlReader。所以,我尝试了这个。

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" />
...
'

如何处理和纠正这个错误?

【问题讨论】:

  • createElement 不能接受 XML 片段。我什至不确定DOMDocument API 中是否有这样的功能。您是否考虑过从(纯文本)文件中删除 &lt;!----&gt;
  • 是的,我稍微考虑过从纯文本中删除 ,但还没有开始实施。该 xml 文件中还有许多其他 cmets,因此到目前为止找到正确的 cmets 似乎太难了。
  • 正如我之前写的,我认为DOMDocument API 中没有这样的功能。 appendXML 似乎是 PHP 独有的。

标签: xml inno-setup xmldocument xml-comments


【解决方案1】:

正如 Martin Prikryl 建议的那样,我通过从纯文本文件中删除注释标签 &lt;!----&gt; 解决了我的问题。为此,我编写了以下函数。

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;

【讨论】:

    猜你喜欢
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2016-05-11
    • 2018-04-13
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多