unit uBugTest;

interface

{$I XpDefine.inc}

uses
{$IFDEF WIN32}
  Windows,
  Forms,
{$ENDIF}
{$IFDEF LINUX}
  QForms,
{$ENDIF}
  TestFramework,
  SysUtils,
  Classes,
  XpParser,
  XpBase;

const
  Test257Line1 = '1 - Test 257 line 1';
  Test257Line2 = '2 - Test 257 line 2';
  Test258Line1 = '1 - Test 258 line 1';
  Test258Line2 = '2 - Test 258 line 2';

type
  TXpBugTests = class(TTestCase)
    protected
      FPar      : TXpParser;
      FStrm264  : TMemoryStream;
      FStrm262  : TMemoryStream;
      FStrm265  : TMemoryStream;
      FStrm267  : TMemoryStream;
      FStrm266  : TMemoryStream;
      FStrm261  : TMemoryStream;
      FStrm261b : TMemoryStream;

      procedure Setup; override;
      procedure Teardown; override;
      procedure Test257Compare(oOwner : TObject;
                               sValue : DOMString);
      procedure Test258Compare(oOwner : TObject;
                               sValue : DOMString);
      procedure Test465OnFuncAvail(oOwner        : TObject;
                                   sFunctionName : DOMString;
                               var bAvailable    : Boolean);
    public
      property Parser : TXpParser
         read FPar;
    published
      procedure Test266;
        { A document should not start with a comment when it also cont }
      procedure Test267;
        { Attributes can be redefined in a non standard way  }
      procedure Test262;
        {  recursive entity declarations are not detected   }
      procedure Test259;
        { Parser does not check validity of characters in document  }
      procedure Test261;
        { Names not checked for validity  }
      procedure Test264;
        {  Invalid character sequences are accepted in comments   }
//      procedure Test265;
//        { Invalid data is accepted in the character data section  }
      procedure Test256_LONG;
        { Parser may crash when reading large files }
      procedure Test257;
        { Parser may loose text if document little endian encoded }
      procedure Test258;
        { Parser does not support UTF-16 with big endian encoding }
      procedure Test260;
        { Parser ignores XML declaration }
      procedure Test263;
        { Including external entities may cause AV }
      procedure Test392;
        { All XSLT implementations must support xsl:version,
          xsl:vendor, xsl:vendor-url }
      procedure Test397;
        { TXpElement.GetElementsByTagNameNS should compare against
          LocalName }
      procedure Test403;
        { TXmlDTDAttlist.CreateDTDAttDefinition should accept nil
          value for oEnumeration parameter }
      procedure Test404;
        { Default value not returned for element attribute }
      procedure Test420;
        { TXpDomImplementation.HasFeature('CORE', 2.0) should
          report True }
      procedure Test465;
        { DOM: function-available implementation does not check for
          standard functions }
      procedure Test443_1;
        { Some things not implemented: XPath SUM function}
      procedure Test443_2;
        { Some things not implemented: DOM's ValidateDocument
          should validate the standalone constraint}
      procedure testParseExtendedCharacters;
        { Issue 2535 - Element and attribute names not properly validated. }
  end;

implementation

uses
  XpChrFlt,
  XpExcept,
  XpDOM;

{ TXpBugTests }

procedure TXpBugTests.Setup;
var
  SList : TStringList;
begin
  inherited;

  FPar := TXpParser.Create(nil);

  {  Invalid character sequences are accepted in comments   }
  FStrm264 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
    SList.Add('<BADDOC>');
    SList.Add('<!-- bad -- comment -->');
    SList.Add('</BADDOC>');
    SList.SaveToStream(FStrm264);
    FStrm264.Position := 0;
  finally
    SList.Free;
  end;

  {  recursive entity declarations are not detected   }
  FStrm262 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
    SList.Add('<!DOCTYPE doc [');
    SList.Add('<!ENTITY outer "This is bad, &inner;">');
    SList.Add('<!ENTITY inner  "So &outer; bad that its ill-formed">');
    SList.Add(']>');
    SList.Add('<BADDOC>');
    SList.Add('</BADDOC>');
    SList.SaveToStream(FStrm262);
    FStrm262.Position := 0;
  finally
    SList.Free;
  end;

  { Invalid data is accepted in the character data section  }
  FStrm265 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
    SList.Add('<BADDOC>');
    SList.Add('  <class_file name="demo.class">');
    SList.Add('  <![CDATA[kjhdsifuyalserhalkjdfhaliusdhf--<-]]>---]]>');
    SList.Add('  </class_file>');
    SList.Add('</BADDOC>');
    SList.SaveToStream(FStrm265);
    FStrm265.Position := 0;
  finally
    SList.Free;
  end;

  { Attributes can be redefined in a non standard way  }
  FStrm267 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
//    SList.Add('<BADDOC>');
    SList.Add('<icon img="smiley" img="frown">');
    SList.Add('</icon>');
//    SList.Add('</BADDOC>');
    SList.SaveToStream(FStrm267);
    FStrm267.Position := 0;
  finally
    SList.Free;
  end;

  {A document should not start with a comment when it also cont }
  FStrm266 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<!-- good comment -->');
    SList.Add('<?xml version="1.0"?>');
    SList.Add('<BADDOC>');
    SList.Add('</BADDOC>');
    SList.SaveToStream(FStrm266);
    FStrm266.Position := 0;
  finally
    SList.Free;
  end;

  { Names not checked for validity  }
  FStrm261 := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
    SList.Add('<1BADDOC>');
    SList.Add('</1BADDOC>');
    SList.SaveToStream(FStrm261);
    FStrm261.Position := 0;
  finally
    SList.Free;
  end;

  { Names not checked for validity  }
  FStrm261b := TMemoryStream.Create;
  SList := TStringList.Create;
  try
    SList.Add('<?xml version="1.0"?>');
    SList.Add('< >');
    SList.Add('</ >');
    SList.SaveToStream(FStrm261b);
    FStrm261b.Position := 0;
  finally
    SList.Free;
  end;
end;
{--------}
procedure TXpBugTests.Teardown;
begin
  FPar.Free;
  FStrm264.Free;
  FStrm262.Free;
  FStrm265.Free;
  FStrm267.Free;
  FStrm266.Free;
  FStrm261.Free;
  FStrm261b.Free;
  inherited;
end;
{--------}
procedure TXpBugTests.Test257Compare(oOwner : TObject;
                                     sValue : DOMString);
var
  IsGood : Boolean;
begin
  IsGood := False;
  if sValue = Test257Line1 then
    IsGood := True
  else if sValue = Test257Line2 then
    IsGood := True;
  Assert(IsGood);
end;
{--------}
procedure TXpBugTests.Test258Compare(oOwner : TObject;
                                     sValue : DOMString);
var
  IsGood : Boolean;
begin
  IsGood := False;
  if sValue = Test258Line1 then
    IsGood := True
  else if sValue = Test258Line2 then
    IsGood := True;
  Assert(IsGood);
end;
{--------}
procedure TXpBugTests.Test465OnFuncAvail(oOwner        : TObject;
                                         sFunctionName : DOMString;
                                     var bAvailable    : Boolean);
begin
  Assert(sFunctionName <> 'function-available',
         'OnFunctionAvailable called for built in function');
end;
{--------}
procedure TXpBugTests.Test256_LONG;
{ Parser may crash when reading large files }
const
  cEntry = 'This is a very long line of junk used to grow a very large' +
           'file that is used to test if large files can trash our ' +
           'favorite XML parser thingy-ma-parser that we purchased ' +
           'for lots of money to enable TurboPower to take over ' +
           'Microsoft and the rest of the world';
var
  Parser     : TXpParser;
  FileStream : TFileStream;
  TempStr    : string;
  FileName   : string;
  Idx        : Integer;
begin
  {if there is enough space, create a 100meg XMLDocument}
{$IFDEF WIN32}
  if DiskFree(0) > (1024 * 100000) then begin
{$ENDIF}
    FileName := ExtractFilePath(Application.ExeName) + 'XMLTest256.xml';
    FileStream := TFileStream.Create(FileName, fmCreate);
    try
      TempStr := '<doc>';
      FileStream.Write(TempStr[1], Length(TempStr));
      for Idx := 1 to 500000 do begin
        TempStr := '<a' + IntToStr(Idx) + '>' + cEntry + '</a' + IntToStr(Idx) + '>';
        FileStream.Write(TempStr[1], length(TempStr));
      end;
      TempStr := '</doc>';
      FileStream.Write(TempStr[1], Length(TempStr));
    finally
      FileStream.Free;
    end;
      Parser := TXpParser.Create(nil);
      try
        try
          if not Parser.ParseDataSource(FileName) then
            Assert(False, Parser.Errors[0]);
        except
          Assert(False, 'Blew up parsing big ''ole file');
        end;
      finally
        Parser.Free;
        DeleteFile(PChar(FileName));
      end;
{$IFDEF WIN32}
  end else
    Assert(False, 'Not enough disk space for test');
{$ENDIF}
end;
{--------}
procedure TXpBugTests.Test257;
  { Parser may loose text if document little endian encoded }
var
  aStream : TMemoryStream;
  Parser    : TXpParser;
  DOM : TXpObjModel;
  TempStr   : string;
begin
  {Build little endian doc using OutStream}
  {put in element data to check = element1}
  aStream := TMemoryStream.Create;
  try
    DOM := TXpObjModel.Create(nil);
    try
      TempStr := '<doc>' +
                 '<line1>' + Test257Line1 + '</line1>' +
                 '<line2>' + Test257Line2 + '</line2>' +
                 '</doc>';
      Assert(DOM.LoadMemory(TempStr[1], Length(TempStr)),
             'DOM failed to load document: ' + DOM.Errors[0]);
      DOM.SaveToStream(aStream);
    finally
      DOM.Free;
    end;
    {make parser and override OnElement to check data}
    Parser := TXpParser.Create(nil);
    try
      Parser.OnCharData := Test257Compare;
      aStream.Position := 0;
      try
        Assert(Parser.ParseMemory(aStream.Memory^, aStream.Size),
               'Received errors while parsing');
      except
        Assert(False, 'Threw exception while parsing');
      end;
    finally
      Parser.Free;
    end;
  finally
    aStream.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test258;
  { Parser does not support UTF-16 with big endian encoding }
var
  aStream : TMemoryStream;
  Parser    : TXpParser;
  DOM : TXpObjModel;
  TempStr   : string;
begin
  {Build little endian doc using OutStream}
  {put in element data to check = element1}
  aStream := TMemoryStream.Create;
  try
    DOM := TXpObjModel.Create(nil);
    try
      TempStr := '<doc>' +
                 '<line1>' + Test258Line1 + '</line1>' +
                 '<line2>' + Test258Line2 + '</line2>' +
                 '</doc>';
      Assert(DOM.LoadMemory(TempStr[1], Length(TempStr)),
             'DOM failed to load document: ' + DOM.Errors[0]);
      DOM.SaveToStream(aStream);
    finally
      DOM.Free;
    end;
    {make parser and override OnElement to check data}
    Parser := TXpParser.Create(nil);
    try
      Parser.OnCharData := Test258Compare;
      aStream.Position := 0;
      try
        Assert(Parser.ParseMemory(aStream.Memory^, aStream.Size),
               'Received errors while parsing');
      except
        Assert(False, 'Threw exception while parsing');
      end;
    finally
      Parser.Free;
    end;
  finally
    aStream.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test259;
{ Parser does not check validity of characters in document  }
begin
  Assert(True);

  { Fixed. Integrating Julian's streaming code fixes the problem.
    A proper exception is raised at the filter level to deal with this issue.
    A test case can be found in the filter test suite }
end;
{--------}
procedure TXpBugTests.Test260;
{ Parser ignores XML declaration }
var
  Parser  : TXpParser;
  TempStr : string;
begin
  TempStr := '<?xml version="2.2"?><doc></doc>';
  Parser := TXpParser.Create(nil);
  try
    { The parse should fail because the XML document has a version
      number that we do not currently support.}
    Assert(not Parser.ParseMemory(TempStr[1], Length(TempStr)),
           'Parser missed invalid version number');
    Assert(Pos('XMLPartner does not support XML specification',
           Parser.GetErrorMsg(0)) <> 0);
  finally
    Parser.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test261;
{ Names not checked for validity  }
var
  Mem : Pointer;
begin
  Mem := FStrm261.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm261.Size));

  TearDown;
  Setup;

  Mem := FStrm261b.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm261b.Size));
end;
{--------}
procedure TXpBugTests.Test262;
{  recursive entity declarations are not detected   }
var
  Mem : Pointer;
begin
  Exit; //bad test, but this gets tested during the Oasis/good tests
  Mem := FStrm262.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm262.Size));
end;
{--------}
procedure TXpBugTests.Test263;
{ Including external entities may cause AV }
var
  Parser     : TXpParser;
  FileStream : TFileStream;
  TempStr    : string;
  Path       : string;
begin
 { This tests only confirms that the parser can include external
   entities. The size is tested with test 256. }
  Path := ExtractFilePath(Application.ExeName);
  if FileExists(Path + '003-1.ent') then
    try
      DeleteFile(PChar(Path + '003-1.ent'));
      DeleteFile(PChar(Path + '003-2.ent'));
    except
    end;

  if FileExists(Path + '003-2.ent') then
    try
      DeleteFile(PChar(Path + '003-2.ent'));
    except
    end;

  { Create the 003-1.ent file so that it contains the correct path
    to the other external entity (003-2.ent).}
  FileStream := TFileStream.Create(Path + '003-2.ent', fmCreate);
  FileStream.Free;
  try
    FileStream := TFileStream.Create(Path + '003-1.ent', fmCreate);
    try
      TempStr := '<!ELEMENT doc EMPTY><!ENTITY % e SYSTEM "' +
                 Path + '003-2.ent"><!ATTLIST doc a1 CDATA %e; "v1">';
      FileStream.Write(TempStr[1], Length(TempStr));
    finally
      FileStream.Free;
    end;

    TempStr := '<!DOCTYPE doc SYSTEM "' + Path + '003-1.ent"><doc></doc>';

    Parser := TXpParser.Create(nil);
    try
      try
        Assert(Parser.ParseMemory(TempStr[1], Length(TempStr)),
               Parser.GetErrorMsg(0));
      except
        on e:Exception do
          Assert(False, e.Message);
      end;
    finally
      Parser.Free;
    end;
  finally
    DeleteFile(PChar(Path + '003-1.ent'));
    DeleteFile(PChar(Path + '003-2.ent'));
  end;
end;
{--------}
procedure TXpBugTests.Test264;
{  Invalid character sequences are accepted in comments   }
var
  Mem : Pointer;
begin
  Mem := FStrm264.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm264.Size));
end;
{--------}
procedure TXpBugTests.Test266;
{ A document should not start with a comment when it also contains
  an XML declaration }
var
  Mem : Pointer;
begin
  Mem := FStrm266.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm266.Size));
end;
{--------}
procedure TXpBugTests.Test267;
{ Attributes can be redefined in a non standard way  }
var
  Mem : Pointer;
begin
  Mem := FStrm267.Memory;
  Assert(not Parser.ParseMemory(Mem^, FStrm267.Size));
end;
{--------}
procedure TXpBugTests.Test392;
{ All XSLT implementations must support xsl:version,
  xsl:vendor, xsl:vendor-url }
var
  TheDOM  : TXpObjModel;
  TempStr : string;
begin
  TheDOM := TXpObjModel.Create(nil);
  try
    TempStr := '<doc></doc>';
    TheDOM.LoadMemory(TempStr[1], Length(TempStr));

    {This Assert statement will have to be modified for the Pro version
     and each time we implement a new XSL version. We're not able to
     retrieve the version number as a number using StrToFloat, because
     it uses the local decimal separator and "." is the only allowed
     decimal separator per the XSL spec ver 1.1, section 2.3 and the
     production for a number (http://www.w3.org/TR/xpath#NT-Number).}

     {XSL is not supported in the standard version so it uses 0.0 as
      the version number.}
{$IFDEF XPDPRO}
    Assert(
      TheDOM.DocumentElement.SelectString('system-property(''xsl:version'')') =
      '1.0', 'Not retrieving XSL version correctly');
{$ELSE}
    Assert(
      TheDOM.DocumentElement.SelectString('system-property(''xsl:version'')') =
      '0.0', 'Not retrieving XSL version correctly');
{$ENDIF}
    Assert(
      TheDOM.DocumentElement.SelectString('system-property(''xsl:vendor'')') =
      XpVendor, 'Not retrieving XSL vendor correctly');
    Assert(
      TheDOM.DocumentElement.SelectString('system-property(''xsl:vendor-url'')') =
      XpVendorURL, 'Not retrieving XSL vendor URL correctly');
  finally
    TheDOM.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test397;
{ TXpElement.GetElementsByTagNameNS should compare against
  LocalName }
var
  TheDOM   : TXpObjModel;
  NodeList : TXpNodeList;
  TempStr  : string;
begin
  TempStr := '<doc>' +
               '<item1></item1>' +
               '<item2></item2>' +
               '<item3></item3>' +
             '</doc>';

  NodeList := nil;
  TheDOM := TXpObjModel.Create(nil);
  try
    TheDOM.LoadMemory(TempStr[1], Length(TempStr));
    NodeList := TheDOM.DocumentElement.GetElementsByTagNameNS('', 'item2');
    Assert(NodeList.Length = 1);
  finally
    NodeList.Free;
    TheDOM.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test403;
  { TXpDTDAttlist.CreateDTDAttDefinition should accept nil
    value for oEnumeration parameter }
var
  DTDAttDefList : TXpDTDAttlist;
  oDTDAttDef : TXpDTDAttDefinition;
begin
  DTDAttDefList := TXpDTDAttlist.Create;
  try
    try
      oDTDAttDef := DTDAttDefList.CreateDTDAttDefinition('test', 1, nil, 1, 'hello');
      try
        DTDAttDefList.AppendChild(oDTDAttDef);
      finally
        oDTDAttDef.Release;
      end;
    except
      Assert(False,
             'Could not create DTDAttDefinition w/nil for Enumeration');
    end;
  finally
    DTDAttDefList.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test404;
  { Default value not returned for element attribute }
var
  TheDOM     : TXpObjModel;
  FileStream : TFileStream;
  TempStr    : string;
  FilePath   : string;
begin
  TempStr := '<!ELEMENT doc EMPTY>' +
             '<!ATTLIST doc a1 CDATA "v1">';
  FilePath := ExtractFilePath(Application.ExeName) + 'test404.ent';
  FileStream := TFileStream.Create(FilePath, fmCreate);
  FileStream.Write(TempStr[1], Length(TempStr));
  FileStream.Position := 0;
  FileStream.Free;
  try
    TheDOM := TXpObjModel.Create(nil);
    try
      TempStr := '<!DOCTYPE doc SYSTEM "' + FilePath + '">' +
                 '<doc></doc>';
      if TheDOM.LoadMemory(TempStr[1], Length(TempStr)) then
        Assert(
          TheDOM.DocumentElement.GetAttribute('a1') = 'v1',
          'Didn''t retrieve default value for element')
      else
        Assert(False, 'DOM could not load the document, errors: ' +
                      TheDOM.Errors.Text);
    finally
      TheDOM.Free;
    end;
  finally
    DeleteFile(PChar(FilePath));
  end;
end;
{--------}
procedure TXpBugTests.Test420;
  { TXpDomImplementation.HasFeature('CORE', 2.0) should
    report True }
var
  TheDOM : TXpObjModel;
begin
  TheDOM := TXpObjModel.Create(nil);
  try
    Assert(
      TheDOM.Document.DomImplementation.HasFeature('CORE', '2.0'),
      'HasFeature(''CORE'', ''2.0'') returned False');
  finally
    TheDOM.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test465;
  { DOM: function-available implementation does not check for
    standard functions }
var
  TheDOM : TXpObjModel;
  sStr : string;
begin
  TheDOM := TXpObjModel.Create(nil);
  try
    sStr := '<root><a/></root>';
    TheDOM.LoadMemory(sStr[1], Length(sStr));
    TheDOM.Document.OnFunctionAvailable := Test465OnFuncAvail;

    TheDOM.DocumentElement.SelectBoolean(
      'function-available(''function-available'')');
  finally
    TheDOM.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test443_1;
  { Some things not implemented: XPath SUM function}
var
  TheDOM  : TXpObjModel;
  TempStr : string;
begin
  TempStr := '<results group="A">' +
                '<match>' +
                  '<date>10-Jun-98</date>' +
                  '<team score="2">Brazil</team>' +
                  '<team score="1">Scotland</team>' +
                '</match>' +
                '<match>' +
                  '<date>10-Jun-98</date>' +
                  '<team score="2">Morocco</team>' +
                  '<team score="2">Norway</team>' +
                '</match>' +
                '<match>' +
                  '<date>16-Jun-98</date>' +
                  '<team score="1">Scotland</team>' +
                  '<team score="1">Norway</team>' +
                '</match>' +
                '<match>' +
                  '<date>16-Jun-98</date>' +
                  '<team score="3">Brazil</team>' +
                  '<team score="0">Morocco</team>' +
                '</match>' +
                '<match>' +
                  '<date>23-Jun-98</date>' +
                  '<team score="1">Brazil</team>' +
                  '<team score="2">Norway</team>' +
                '</match>' +
                '<match>' +
                  '<date>23-Jun-98</date>' +
                  '<team score="0">Scotland</team>' +
                  '<team score="3">Morocco</team>' +
                '</match>' +
             '</results>';
  TheDOM := TXpObjModel.Create(nil);
  try
    TheDOM.LoadMemory(TempStr[1], Length(TempStr));
    Assert(
      TheDOM.DocumentElement.SelectNumber('sum(//team/@score)') = 18,
      'Didn''t XPath:SUM() correctly');
  finally
    TheDOM.Free;
  end;
end;
{--------}
procedure TXpBugTests.Test443_2;
{ Some things not implemented: DOM's ValidateDocument
  should validate the standalone constraint}
var
  TheDOM     : TXpObjModel;
  FileStream : TFileStream;
  TempStr    : string;
  FilePath   : string;
begin
  { We need a DTD to test against}
  TempStr := '<!-- ======= The BookCatalog DTD (''Basic'' version) ======= -->' +
             '<!ELEMENT  BookCatalog (Catalog, Publisher+, Book*) >' +
             '<!-- <Catalog> section -->' +
             '<!ELEMENT  Catalog (CatalogTitle, CatalogDate) >' +
             '<!ELEMENT  CatalogTitle  (#PCDATA) >' +
             '<!ELEMENT  CatalogDate   (#PCDATA) >' +
             '<!-- <Publisher> section -->' +
             '<!ELEMENT  Publisher (CorpName, Website*, Address) >' +
             '<!ELEMENT  CorpName  (#PCDATA) >' +
             '<!ELEMENT  Website   (#PCDATA) >' +
             '<!ELEMENT  Address (Street*, City, Region?, PostalCode?, Country) >' +
             '<!ELEMENT  Street      (#PCDATA) >' +
             '<!ELEMENT  City        (#PCDATA) >' +
             '<!ELEMENT  Region      (#PCDATA) >' +
             '<!ELEMENT  PostalCode  (#PCDATA) >' +
             '<!ELEMENT  Country     (#PCDATA) >' +
             '<!-- <Book> and <Author> section -->' +
             '<!ELEMENT  Book (ISBN, Title, Author+, Editor*, Abstract?, Pages, Price, Subjects?) >' +
             '<!ELEMENT  ISBN    (#PCDATA) >' +
             '<!ELEMENT  Title   (#PCDATA) >' +
             '<!ELEMENT  Author  (#PCDATA) >         <!-- Just a placeholder for now -->' +
             '<!ELEMENT  Editor  (#PCDATA) >         <!-- Ditto -->' +
             '<!ELEMENT  Pages   (#PCDATA) >' +
             '<!ELEMENT  Price   (#PCDATA) >' +
             '<!-- ======= END of BookCatalog DTD ======= -->';

  FilePath := ExtractFilePath(Application.ExeName) + 'test443_2.dtd';
  FileStream := TFileStream.Create(FilePath, fmCreate);
  FileStream.Write(TempStr[1], Length(TempStr));
  FileStream.Position := 0;
  FileStream.Free;

  TheDOM := TXpObjModel.Create(nil);
  try
    TempStr := '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' +
               '<!DOCTYPE BookCatalog SYSTEM "' + FilePath + '" >' +
               '<BookCatalog>' +
               '  <Catalog>' +
               '    <CatalogTitle>The Wrox BookCatalog (''Basic'' version)</CatalogTitle>' +
               '    <CatalogDate>2000-05-23</CatalogDate>' +
               '  </Catalog>' +
               '  <Publisher>' +
               '    <CorpName>Wrox Press Ltd.</CorpName>' +
               '    <Website>www.wrox.com</Website>' +
               '    <Address>' +
               '      <Street>Arden House</Street>' +
               '      <Street>1102 Warwick Road</Street>' +
               '      <Street>Acocks Green</Street>' +
               '      <City>Birmingham</City>' +
               '      <Region>England</Region>' +
               '      <PostalCode>B27 6BH</PostalCode>' +
               '      <Country>UK</Country>' +
               '    </Address>' +
               '  </Publisher>' +
               '  <Publisher>' +
               '    <CorpName>Wrox Press Inc.</CorpName>' +
               '    <Website>www.wrox.com</Website>' +
               '    <Address>' +
               '      <Street>29 S LaSalle St, Suite 520</Street>' +
               '      <City>Chicago</City>' +
               '      <Region>IL</Region>' +
               '      <PostalCode>60603</PostalCode>' +
               '      <Country>USA</Country>' +
               '    </Address>' +
               '  </Publisher>' +
               '  <Book>' +
               '    <ISBN>1-861003-11-0</ISBN>' +
               '    <Title>Professional XML</Title>' +
               '    <Author>Didier Martin</Author>' +
               '    <Author>Mark Birbeck</Author>' +
               '    <Author>Michael Kay</Author>' +
               '    <Author>Brian Loesgen</Author>' +
               '    <Author>Jon Pinnock</Author>' +
               '    <Author>Steven Livingstone</Author>' +
               '    <Author>Peter Stark</Author>' +
               '    <Author>Kevin Williams</Author>' +
               '    <Author>Richard Anderson</Author>' +
               '    <Author>Stephen Mohr</Author>' +
               '    <Author>David Baliles</Author>' +
               '    <Author>Bruce Peat</Author>' +
               '    <Author>Nikola Ozu</Author>' +
               '    <Editor>Jon Duckett</Editor>' +
               '    <Editor>Peter Jones</Editor>' +
               '    <Editor>Karli Watson</Editor>' +
               '    <Pages>1169</Pages>' +
               '    <Price>$49.99</Price>' +
               '  </Book>' +
               '</BookCatalog>';
    Assert(TheDOM.LoadMemory(TempStr[1], Length(TempStr)),
           'DOM could not load the document, errors: ' + TheDOM.Errors.Text);
      { This one should be valid}
    Assert(TheDOM.ValidateDocument, 'Document failed to validate.');

    { Test one that should fail}
    TempStr := '<?xml version="1.0" standalone="yes"?>' +
               '<!DOCTYPE doc SYSTEM "' + FilePath + '" >' +
               '<doc></doc>';
    TheDOM.LoadMemory(TempStr[1], Length(TempStr));
    Assert(not TheDOM.ValidateDocument);
  finally
    TheDOM.Free;
  end;
  DeleteFile(PChar(FilePath));
end;
{--------}
procedure TXpBugTests.testParseExtendedCharacters;
 { Issue 2535 - Element and attribute names not properly validated. }
var
  XMLStr : string;
begin
  XMLStr := #$EF + #$BB + #$BF + //Force the character encoding
            '<?xml version="1.0" encoding="ISO-8859-1"?>' +
            '<root>' +
            '  <Test זרו="&#230;&#248;&#229;"/>' +
            '</root>';

  Assert(Parser.ParseMemory(XMLStr[1], Length(XMLStr)),
         Parser.GetErrorMsg(0));
end;
{---------------------------------------------------------------------}
initialization
  RegisterTest('Bug Tests', TXpBugTests);
end.
