[Delphi] [XML] Ik mis een list

Pagina: 1
Acties:

  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 14:12
ben me voor het eerst aan het verdiepen in de XML-functies van Delphi, en nu valt me bij mijn programma iets vreemds op. Ik gebruik de volgende (ingekorte XSD).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="UTF-8" ?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xdb="http://www.borland.com/schemas/delphi/6.0/XMLDataBinding" elementFormDefault="qualified">
  <xs:element name="Regio">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Regio" minOccurs="0" maxOccurs="unbounded" /> 
        <xs:element ref="Parts" minOccurs="0" maxOccurs="unbounded" /> 
      </xs:sequence>
      <xs:attribute name="Long" type="xs:string" use="required" /> 
      <xs:attribute name="Short" type="xs:string" use="optional" /> 
    </xs:complexType>
  </xs:element>
  <xs:element name="Parts">
    <xs:complexType>
      <xs:sequence>
        <xs:element ref="Leg" minOccurs="0" maxOccurs="unbounded" /> 
      </xs:sequence>
    </xs:complexType>
  </xs:element>
  <xs:element name="Leg">
    <xs:complexType>
      <xs:attribute name="item" type="xs:string" use="required" /> 
    </xs:complexType>
  </xs:element>
</xs:schema>


Wanneer ik deze XSD (de complete versie) door de XML Binding Wizard haal, maakt hij onder andere de volgende interfaces aan:
Delphi:
1
2
3
4
5
  TXMLRegio = class;
  TXMLRegioList = class;
  TXMLParts = class;
  TXMLPartsList = class;
  TXMLLeg = class;


Er bestaan zoals in de xsd te zien is, meerdere regio's per regio, meerdere parts per regio en meerdere legs per part.

Maar... waarom krijg ik van de wizard geen IXMLLegList terug.
De volledige vorm van TXMLParts is:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
{ TXMLParts }

  TXMLParts = class(TXMLNodeCollection, IXMLParts)
  protected
    { IXMLParts }
    function Get_Leg(Index: Integer): IXMLLeg;
    function Add: IXMLLeg;
    function Insert(const Index: Integer): IXMLLeg;
  public
    procedure AfterConstruction; override;
  end;


De enige manier om nu te ontdekken hoeveel legs er in 1 part zitten in de index te verhogen tot ik eruit knal. Terwijl er als onderdeel bij de lists een mooie count-function bestaat.

Ik kan heel bijdehant natuurlijk handmatig een IXMLLegList en een TXMLLegList aanmaken, maar dan raak ik die waarschijnlijk kwijt zodra ik de XSD aanpas en opnieuw door de wizard haal.

Iemand een suggestie?

  • LordLarry
  • Registratie: Juli 2001
  • Niet online

LordLarry

Aut disce aut discede

In de wizard kan je ook dit soort wijzigingen in de structuur aanbregen. De wizard produceerd ook een configuratie bestandje zodat je opnieuw de wizard kan starten met dezelfde instellingen.

We adore chaos because we like to restore order - M.C. Escher


  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Omdat daar geen
code:
1
2
3
<xs:sequence>
...
</xs:sequence>

staat?

Wie trösten wir uns, die Mörder aller Mörder?


  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 14:12
Confusion schreef op maandag 26 september 2005 @ 22:37:
Omdat daar geen
code:
1
2
3
<xs:sequence>
...
</xs:sequence>

staat?
Volgens mij wel in regel 15 en 17. Die heb ik ook zelf toegevoegd, want die ontbraken oorspronkelijk wel. Maar het toevoegen van die regels bracht geen verandering voor de wizard.

De wizard ziet de legs ook wel als repeating getuige de wizard:
Afbeeldingslocatie: http://home.versatel.nl/jeroenpetra/delphixml.JPG

maar handelt er niet naar. En het datatype verbeteren naar IXMLLegList zet ook geen zoden aan de dijk. Het enige dat dan veranderd is

Delphi:
1
2
3
4
5
6
7
8
9
10
11
{ TXMLParts }

  TXMLParts = class(TXMLNodeCollection, IXMLParts)
  protected
    { IXMLParts }
    function Get_Leg(Index: Integer): IXMLLegList;
    function Add: IXMLLeg;
    function Insert(const Index: Integer): IXMLLeg;
  public
    procedure AfterConstruction; override;
  end;


De definitie van IXMLLegList wordt niet aangemaakt door de wizard, dus daar heb ik niets aan.

Blijft daarnaast de vraag waarom maakt hij niet een nette list aan met een Items-property en een count daaraan vast.

[ Voor 85% gewijzigd door jvdmeer op 26-09-2005 23:48 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 28-04 18:15

Tomatoman

Fulltime prutser

Kijk eens naar de TXMLNodeCollection.Count property.

offtopic:
'Regio' is een Nederlands woord, terwijl de rest van je schema Engelstalig is. :)

[ Voor 45% gewijzigd door Tomatoman op 27-09-2005 00:25 ]

Een goede grap mag vrienden kosten.


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 28-04 18:15

Tomatoman

Fulltime prutser

Ik heb er even een voorbeeld bijgepakt om te kijken wat voor code de XML Data Binding Wizard in Delphi 7 ervoor genereerde.

Dit is de ingekorte .XSD:
XML:
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="unqualified" attributeFormDefault="unqualified">
    <xs:complexType name="Header">
        <xs:sequence>
            <xs:element name="GlobalComments" type="Comments"/>
        </xs:sequence>
    </xs:complexType>
    <xs:complexType name="Comments">
        <xs:sequence>
            <xs:element name="Comment" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
</xs:schema>


En dit maakte de wizard ervan:
Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{ IXMLHeader }

  IXMLHeader = interface(IXMLNode)
    ['{BB189B34-1109-48DF-844B-CB4259E2B7C0}']
    { Property Accessors }
    function Get_GlobalComments: IXMLComments;
    { Methods & Properties }
    property GlobalComments: IXMLComments read Get_GlobalComments;
  end;

{ IXMLComments }

  IXMLComments = interface(IXMLNodeCollection)
    ['{0D4A3D98-C7CE-4ED1-8D94-5FA777E90334}']
    { Property Accessors }
    function Get_Comment(Index: Integer): WideString;
    { Methods & Properties }
    function Add(const Comment: WideString): IXMLNode;
    function Insert(const Index: Integer; const Comment: WideString): IXMLNode;
    property Comment[Index: Integer]: WideString read Get_Comment; default;
  end;
Ten eerste blijkt uit de declaratie van IXMLHeader dat de wizard probleemloos collections genereert. In de helpfiles staat verder:
Typically, applications do not work directly with TXMLNodeCollection. Instead, they use the IXMLNodeCollection interface or the IXMLNodeCollection descendant that is implemented by a TXMLNodeCollection descendant.
TXMLNodeCollection.Count mag dan wel protected zijn, de interface property IXMLNodeCollection.Count is ook buiten de TXMLNodeCollection descendant toegankelijk. Zolang je IXMLHeader.GlobalComments als een interface behandelt en niet als een class, kun je daardoor probleemloos door alle comments itereren:
Delphi:
1
2
3
4
5
6
procedure Foo(Header: IXMLHeader);
var
  i: Integer;
begin
  for i := 0 to Header.GlobalComments.Count - 1 do
    ...

Een goede grap mag vrienden kosten.


  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 14:12
tomatoman schreef op dinsdag 27 september 2005 @ 00:21:
Delphi:
1
2
3
4
5
6
procedure Foo(Header: IXMLHeader);
var
  i: Integer;
begin
  for i := 0 to Header.GlobalComments.Count - 1 do
    ...
Ga ik vanavond proberen, CodeInsight (zo heet het toch?) geeft count niet als property. En er staat ook een rood kringeltje onder tydens het typen.
tomatoman schreef op maandag 26 september 2005 @ 23:43:
offtopic:
'Regio' is een Nederlands woord, terwijl de rest van je schema Engelstalig is. :)
offtopic:
Volgens mij is 'punt' ook nederlandstalig. En dan blijkt het engelse woord 'leg' ook nog in het nederlands als jargon te worden gebruikt. De enige vreemde eend in de bijt is 'parts', maar het nederlandse alternatief ('deel' of evt. 'gedeelte' of het bijbehorende mv) daarvoor vond ik niet lekker in de mond liggen.

Mijn code (ik werk grotendeels voor mijzelf) in hobbyprojectjes, is grotendeels nederlandstalig, tenzij dat niet lekker bekt.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 28-04 18:15

Tomatoman

Fulltime prutser

jvdmeer schreef op dinsdag 27 september 2005 @ 10:11:
[...]

Ga ik vanavond proberen, CodeInsight (zo heet het toch?) geeft count niet als property. En er staat ook een rood kringeltje onder tydens het typen.
Dat zou net het verschil kunnen zijn tussen het gebruiken van de class reference of de interface reference. In de class is Count protected (en dus verwacht ik een rood kringeltje), terwijl de Count property van de interface public is. Dat neemt niet weg dat ik het logischer had gevonden als TXMLNodeCollection.Count public zou zijn geweest.

Wil je persé met classes in plaats van interfaces werken, dan kun je altijd nog de protected members toegankelijk maken met de volgende truc:
Delphi:
1
2
3
4
5
6
7
type
  TXMLNodeCollectionHack = class(TXMLNodeCollection);

function NodeCount(NodeCollection: TXMLNodeCollection): Integer;
begin
  Result := TXMLNodeCollectionHack(NodeCollection).Count;
end;

[ Voor 34% gewijzigd door Tomatoman op 27-09-2005 11:18 ]

Een goede grap mag vrienden kosten.


  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 14:12
Ik heb het even gecheckt. En het rode kringeltje verschijnt bij het typen. Echter nadat het project eenmaal gecompileerd is, verdwijnt het kringeltje.

Mijn probleem is dus opgelost.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 28-04 18:15

Tomatoman

Fulltime prutser

Verdwijnt het kringeltje na compileren bij IXMLNodeCollection.Count of juist bij TXMLNodeCollection.Count?

Een goede grap mag vrienden kosten.


  • jvdmeer
  • Registratie: April 2000
  • Laatst online: 14:12
I
offtopic:
Mijn kortste reactie ooit!
Pagina: 1