uses
  derror,
  dstrnum,
  dstream,
  dstreammem,
  dstreamfile,
  dxml_sax;

type
TXmlDumper = object(TXmlReader)
  procedure OnOpenTagBegin(const Name: AnsiString); virtual;
  procedure OnAttribute(const Name, Value: AnsiString); virtual;
  procedure OnOpenTagEnd(const Name: AnsiString); virtual;
  procedure OnContent(const Content: AnsiString); virtual;
  procedure OnCloseTag(const Name: AnsiString); virtual;
end;

procedure TXmlDumper.OnOpenTagBegin(const Name: AnsiString);
begin
  inherited;
  Writeln('Open tag: ', Name, ', current depth: ', Depth);
end;

procedure TXmlDumper.OnAttribute(const Name, Value: AnsiString);
begin
  inherited;
  Writeln('Attribute: ', Name, '=', Value);
end;

procedure TXmlDumper.OnOpenTagEnd(const Name: AnsiString);
begin
  inherited;
end;

procedure TXmlDumper.OnContent(const Content: AnsiString);
var
  Unescaped: AnsiString;
  C: AnsiChar;
begin
  inherited;
  Unescaped := UnescapeHTML(Content);
  Write('Content: ');
  for C in Unescaped do begin
    if (Ord(C) > 32) and (Ord(C) < 128) then begin
      Write(C);
    end else
      Write('#' + IntToHex(Ord(C), 2));
  end;
  Writeln;
end;

procedure TXmlDumper.OnCloseTag(const Name: AnsiString);
begin
  Writeln('Close tag: ', Name, ', current depth: ', Depth);
  inherited;
end;

var
  XmlDumper: TXmlDumper;
  XmlIgnore: TXmlReader;
  Error: TError;

procedure Test(const S: AnsiString; Dump: Boolean = False);
var
  Reader: PXmlReader;
begin
  if Dump then begin
    Reader := @XmlDumper;
  end else
    Reader := @XmlIgnore;
  if not ParseXml(S, Reader, @Error) then begin
    Writeln('Failed reading ', S, ': ', Error.Msg);
  end else
    Writeln('Loaded: ', S);
end;

begin
  XmlDumper.Init;
  XmlIgnore.Init;
  Test('test.xml');
  Test('consolas_regular_14.xml');
  Test('test_fail1.xml');
  Test('test_fail2.xml');
  Test('test_fail3.xml');
  Test('test_fail4.xml');
  Test('test_fail5.xml');
  Test('test_fail6.xml');
  Test('test_fail7.xml');
  Test('test_fail8.xml');
  Test('test_fail9.xml');
  Test('test_fail10.xml');
  Test('test_fail11.xml');
  Test('test_fail12.xml');
  Test('test_pass.xml', True);
  XmlIgnore.Done;
  XmlDumper.Done;
end.
