Forum Delphi.cz

Delphi => Obecné => Téma založeno: delirium 28-07-2021, 19:40:31

Název: Ako na XML parser?
Přispěvatel: delirium 28-07-2021, 19:40:31
Zdravim,

potrebujem poradit, mam XML subor.

Kód: Delphi [Vybrat]
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, XMLIntf, XMLDoc, StdCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     Button1: TButton;
  12.     Memo1: TMemo;
  13.     procedure Button1Click(Sender: TObject);
  14.   private
  15.     { Private declarations }
  16.   public
  17.     { Public declarations }
  18.   end;
  19.  
  20. const
  21.   TestXML = '<?xml version="1.0" encoding="UTF-8"?>' +
  22.             '<SeasonStatistics>' +
  23.             '<Team>' +
  24.             '<Player last_name="Correia Filho" player_id="168805" shirtNumber="23" first_name="Roberto Dias" position="Defender" known_name="Roberto Dias">' + // rozsirene data
  25.             '<Stat name="Games Played">1</Stat>' + // zobrazi sa
  26.             '<Stat name="Blocks">2</Stat>' + // nezobrazi sa
  27.             '<Stat name="Leftside Passes">10</Stat>' + // nezobrazi sa
  28.             '</Player>' +
  29.  
  30.             '<Player first_name="David" position="Midfielder" last_name="Cobnan" player_id="545262" shirtNumber="0" />' + // nie su rozsirene data, error: "could not convert variant of type (null) into type (string)"
  31.             '</Team>' +
  32.             '</SeasonStatistics>';
  33. var
  34.   Form1: TForm1;
  35.  
  36. implementation
  37.  
  38. {$R *.dfm}
  39.  
  40. procedure TForm1.Button1Click(Sender: TObject);
  41. var
  42.   Doc: IXMLDocument;
  43.   Root: IXMLNode;
  44.   PersonList: IXMLNodeList;
  45.   Person: IXMLNode;
  46.   i: Integer;
  47. begin
  48.   Memo1.Clear;
  49.   Doc := LoadXMLData(TestXML);
  50.   Doc.Active := True;
  51.   Root := Doc.DocumentElement;
  52.   PersonList := Root.ChildNodes['Team'].ChildNodes;
  53.   Person := PersonList.First;
  54.   while Assigned(Person) do
  55.   begin
  56. //    Memo1.Lines.Add(Person.ChildNodes['Stat name="Blocks"'].Text);  // error...
  57.  
  58.     Memo1.Lines.Add(Person.ChildValues['Stat']); // iba jeden zaznam z nodu stat... [1] !!!
  59.     Person:= Person.NextSibling;
  60.   end;
  61. end;

Ako dokopat v Delphi 7 (PRO), aby som dokazal zobrazit "Stat name="Games Played"", "Stat name="Blocks"", first_name="David" a aby to nehadzalo chybu  "could not convert variant of type (null) into type (string)"?

Dik.

Martin
Název: Re:Ako na XML parser?
Přispěvatel: Stanislav Hruška 28-07-2021, 20:20:03
Ja sa v tom houby vyznám. Ale oznam jasne hovorí, že je očakávaný string a Ty tam máš null = čiže nič. V prvom rade by som sa pozrel, či sú pre Person správne hodnoty. Očakávam, že Person síce neukazuje že je nil, ale v skutočnosti je
Test Assigned() ma už neraz "sklamal". Stačí čosi uvoľniť a nenastaviť na nil.
Název: Re:Ako na XML parser?
Přispěvatel: pepak 29-07-2021, 05:45:54
Pokud bych to chtěl mít v Delphi s plnou parádou, tak bych si na tvém místě sehnal k tomu XML ještě příslušný XSD soubor, který popisuje jeho strukturu - buď bývá součástí specifikace dat, neo jde s rizikem toho, že nebude úplně přesný, dovodit z příkladů XML. Jakmile totiž máš XSD, tak můžeš použít vestavěný XSD importer, který ti vygeneruje sadu interfaců pro zpracování tvého XML. Následně už s daty pracuješ velmi jednoduše, v tvém případě bys použil něco jako NactenySoubor.SeasonStatistics.Team.Player.Stat[2].Text.

Pokud si to chceš dělat celé sám podobně, jako jsi ukázal na začátku, tak si všimni, že element Stat se může vyskytovat několikrát zatímco ChildValues['Stat'] celkem pochopitelně vrátí jen jednu hodnotu. Pokud se chceš dostat k ostatním, nemůžeš použít ChildValues[], ale musíš proiterovat všechny elementy (ChildNodes), u každého otestovat, jestli jeho Name je 'Stat', a když ano, tak s ním něco udělat.

Co se týče té konverze, čistě by bylo kontrolkovat hodnotu null speciálně, ale dost možná si vystačíš i s jednoduchým nastavením globální proměnné SystemVariants.NullStrictConvert na false.
Název: Re:Ako na XML parser?
Přispěvatel: Jan Fiala 29-07-2021, 06:39:24
A pokud chceš jít jednoduchou cestou, použij třeba JanXMLTree, to je velmi jednoduchá, malá a rychlá implementace XML. Pak muzes pres cestu a iterace pres node <Stat name> přečíst hodnotu, kterou potřebuješ
Název: Re:Ako na XML parser?
Přispěvatel: paja666 29-07-2021, 07:45:03
Jsi na špatném nodu, musíš změnit 1 řádek na (a asi nějak ošetřit případné chybějící detaily atp...)

Kód: Delphi [Vybrat]
  1.   Person := PersonList.First.ChildNodes.First;
Název: Re:Ako na XML parser?
Přispěvatel: František 29-07-2021, 09:03:11
XML data binding
Název: Re:Ako na XML parser?
Přispěvatel: martinnr 29-07-2021, 14:53:20
nemaju tam byt typy TXMLxxx nemiesto IXMLxxx?
Název: Re:Ako na XML parser?
Přispěvatel: pepak 29-07-2021, 15:09:30
nemaju tam byt typy TXMLxxx nemiesto IXMLxxx?
Ne.
Název: Re:Ako na XML parser?
Přispěvatel: Palino 10-08-2021, 09:41:56
skus toto ako nakopnutie (pisane popameti tak tam moze byt chybicka, ale princip by mal sediet):

Players: IXMLDOMNodeList;
Stats: IXMLDOMNodeList;
.
.
.

Players := Root.ChildNodes['Team'].childNodes;

for idx := 0 to Players.Length-1 do
begin
   value:= Players[idx].selectSingleNode('@last_name').text;

   Stats = Players[idx].childNodes;
   for idx2 = 0 to Stats.Length-1 do
      ..

end;