Xml Delphi两次提取标记之间的字符串

Xml Delphi两次提取标记之间的字符串,xml,delphi,text,tags,Xml,Delphi,Text,Tags,我在遇到同样的问题时发现了这段代码:检索两个标记之间的文本。它是有效的,但它只抓住了hello的第一次出现 function ExtractTextInsideGivenTagEx(const Tag, Text: string): string; var StartPos1, StartPos2, EndPos: integer; i: Integer; begin result := ''; StartPos1 := Pos('<' + Tag, Text); En

我在遇到同样的问题时发现了这段代码:检索两个标记之间的文本。它是有效的,但它只抓住了hello的第一次出现

function ExtractTextInsideGivenTagEx(const Tag, Text: string): string;
var
  StartPos1, StartPos2, EndPos: integer;
  i: Integer;
begin
  result := '';
  StartPos1 := Pos('<' + Tag, Text);
  EndPos := Pos('</' + Tag + '>', Text);
  StartPos2 := 0;
  for i := StartPos1 + length(Tag) + 1 to EndPos do
    if Text[i] = '>' then
    begin
      StartPos2 := i + 1;
      break;
    end;


  if (StartPos2 > 0) and (EndPos > StartPos2) then
    result := Copy(Text, StartPos2, EndPos - StartPos2);
end;
函数ExtractTextInsideGivenTagEx(const标记,Text:string):string;
变量
StartPos1,StartPos2,EndPos:integer;
i:整数;
开始
结果:='';
StartPos1:=位置(“”然后
开始
StartPos2:=i+1;
打破
结束;
如果(StartPos2>0)和(EndPos>StartPos2),则
结果:=复制(文本,StartPos2,EndPos-StartPos2);
结束;
但是如果你有呢

hello1hello2hello3hello4


要获取前两个事件的文本吗?

让搜索功能记住
StartPos
,并与可选的偏移量参数一起使用

program Project1;

{$APPTYPE CONSOLE}

function ExtractTextInsideGivenTagEx(const Tag, Text: string;
  var StartPos: Integer): string;
var
  StartPos2, EndPos: Integer;
  i: Integer;
begin
  Result := '';
  StartPos := Pos('<' + Tag, Text, StartPos); // PosEx() in older Delphi versions
  EndPos := Pos('</' + Tag + '>', Text, StartPos);
  StartPos2 := 0;
  for i := StartPos + Length(Tag) + 1 to EndPos do
  begin
    if Text[i] = '>' then
    begin
      StartPos2 := i + 1;
      break;
    end;
  end;
  if (StartPos2 > 0) and (EndPos > StartPos2) then
  begin
    Result := Copy(Text, StartPos2, EndPos - StartPos2);
    StartPos := StartPos2;
  end;
end;

procedure Test(const Sample, aString: String);
var
  s: String;
  StartPos,foundTags: Integer;
begin
  StartPos := 1;
  foundTags := 0;
  repeat
    s := ExtractTextInsideGivenTagEx(Sample, aString, StartPos);
    if (s <> '') then
    begin
      WriteLn(s);
      Inc(StartPos, Length(Sample));
      Inc(foundTags);
    end;
  until (s = '') or (foundTags = 2);
end;

begin
  Test('sample',
    '<sample>hello1</sample><sample>hello2</sample><sample>hello3</sample><sample>hello4</sample>');
  ReadLn;
end.
程序项目1;
{$APPTYPE控制台}
函数ExtractTextInsideGivenTagEx(常量标记,文本:字符串;
var StartPos:Integer):字符串;
变量
StartPos2,EndPos:整数;
i:整数;
开始
结果:='';
StartPos:=Pos(“”)
开始
StartPos2:=i+1;
打破
结束;
结束;
如果(StartPos2>0)和(EndPos>StartPos2),则
开始
结果:=复制(文本,StartPos2,EndPos-StartPos2);
StartPos:=StartPos2;
结束;
结束;
程序测试(常量样本,aString:字符串);
变量
s:字符串;
StartPos,foundTags:Integer;
开始
StartPos:=1;
foundTags:=0;
重复
s:=ExtractTextInsideGivenTagEx(样品、aString、StartPos);
如果是“”,则
开始
书面文件(s);;
Inc(StartPos,长度(样本));
公司(foundTags);
结束;
直到(s=“”)或(foundTags=2);
结束;
开始
测试('样本',
‘你好’;
ReadLn;
结束。


现在为示例XML文本提供了一个解决方案,请注意XML(和HTML)文档可能比本例复杂得多。这意味着在没有完整完整的解析器的情况下很容易丢失标记的跟踪。请参阅。

或者换句话说,使用解析器
您好,谢谢您的示例。我曾尝试将其用于XE6,但它会引发E/a错误。您的意思是I/O错误(英文)。这里的示例在XE6中对我来说很好。您是否将代码粘贴到GUI应用程序中?然后将WriteLn替换为写入备忘录以进行演示的内容。是的,您是对的,WriteLn导致了I/O错误。非常感谢,这真的很有帮助!@LURD我知道您知道这一点,但您应该提到这对我来说不起作用一般XML或HTML,仅适用于特定格式的文本。@DavidHeffernan,是的,如果已知格式适合要搜索的文档,则仅使用简单搜索引擎(或TRegEx)。