Mulți programatori Delphi asociază setările de salvare cu utilizarea INI fișierele din programele dvs. Utilizarea acestei metode în proiecte mai puțin serioase ar trebui evitată, deoarece limitează flexibilitatea, ceea ce împiedică extinderea ulterioară a programului. Merită spus că această abordare este destul de populară datorită ușurinței sale de utilizare și disponibilității instrumentelor încorporate în mediul de dezvoltare.
Cu toate acestea, opțiunea ideală pentru stocarea setărilor programului este structurată XML fișiere. Avantajul lor este că este posibil ca numărul de parametri să nu fie fixat. Pentru a înțelege mai bine acest lucru, să ne uităm la un exemplu specific.
În programul USearch, când faceți clic pe o intrare, apare un meniu contextual, care afișează o listă de articole. Aceste elemente sunt comenzi, care la rândul lor sunt încărcate din fișierul de setări. Dacă setările au fost stocate în INI fișier, atunci programul ar putea salva și încărca un anumit număr de comenzi, de exemplu 10 sau 50. De îndată ce este nevoie de o valoare mai mare, codul va trebui rescris și recompilat corespunzător.
Folosind abordarea folosind XML fișiere, vom putea încărca dinamic toți parametrii secțiunii. Pe lângă toate acestea, fișierul de configurare va deveni mai elegant, fără numerotarea redundantă a parametrilor. In orice caz, mijloace standard a lucra cu XMLîn Delphi au multe dezavantaje, așa că recomand să folosești bibliotecă standard MSXML. De obicei, este inclus în mod implicit sisteme de operare Familia Windows.
A conecta MSXML, trebuie să generăm un fișier de interfață cu o listă a tuturor funcțiilor, importându-l de pe serverul COM. Au fost scrise destul de multe articole detaliate despre cum să importați o interfață, dar vă sugerez să descărcați fișierul MSXML2_TLB.PAS deja gata de utilizare. După ce fișierul este descărcat, plasați-l lângă proiectul dvs. sau plasați-l în folderul lib al mediului Delphi. Astfel, toate programele create vor putea folosi modulul MSXML, trebuie doar să adăugați linia MSXML2_TLB la utilizări.
Pentru claritate, luați în considerare următorul exemplu de utilizare a acestei biblioteci:
Procedura LoadData; var XMLDoc: DOMDocument; Rădăcină: IXMLDOMElement; începe XMLDoc:= CoDOMDocument.Create; XMLDoc.Load("settins.xml"); Root:= XMLDoc.DocumentElement; ShowMessage(Root.SelectSingleNode("size/width").Text); Rădăcină:= zero; XMLDoc:= zero; Sfârşit;
Mai întâi, este creată o instanță a clasei DOMDocument și apoi conținutul fișierului settings.xml este încărcat în memorie. Deoarece conform standardului orice XML fișierul trebuie să conțină o etichetă rădăcină (în în acest caz, config), atunci trebuie să-l obținem folosind funcția DocumentElement. Apoi, conținutul dintre etichete este scos
Aici este folosită metoda SelectSingleNode, care ia ca parametru un șir
În ciuda faptului că subiectul lucrului cu XML în Delphi a fost destul de discutat pe Internet, întrebările pe această temă apar destul de des pe diferite forumuri.
De asemenea, am scris deja, dar aș dori să revin la cazul real al analizei rapide a unui fișier XML și al extragerii datelor, ceea ce am făcut astăzi la serviciu. Nu mi-a luat mai mult de 5 minute să obțin datele necesare.
Fundal. Astăzi trebuia să procesăm date despre programe instalate pe computerele utilizatorilor (da, da, detectăm pirați :)). Departamentul tehnic mi-a furnizat aceste informații, dezlipite de utilizatorii nebănuiți prin rețea folosind WMI. Programul pe care l-au folosit produce rapoarte în format XML. În consecință, mi-au adus un munte de fișiere XML cu o structură destul de complexă din care aveam nevoie doar să extrag numele produselor software instalate. Tratament . După ce am căutat manual câteva fișiere, mi-am dat seama că nu va dura mult să îmbătrânesc și am decis să scriu un convertor mic. După ce am lansat Delphi, am selectat obiectul XML DataBinding din depozit și i-am alimentat unul dintre fișiere. Am lăsat implicit toate setările și parametrii și ca rezultat am creat un modul cu o cantitate mare clase și interfețe pentru accesarea elementelor acestui fișier XML. Nu am petrecut mult timp să-mi dau seama de structura clasei și am trecut imediat la scrierea unui convertor. În noua aplicație de consolă am scris un cod destul de simplu:
programul XML2TXT;
utilizări
Forme
Clase, SysUtils,
SoftwareXML în „SoftwareXML.pas”;
procedura CovertXML2Text;
var
softbase: IXMLSTDSoftwareType;
i:întreg;
sr: TSearchRec;
CurDir: șir;
ExportFile: TStringList;
ÎNCEPE
CurDir:= IncludeTrailingPathDelimiter(ExtractFilePath(Application.ExeName));
dacă FindFirst(CurDir+"*.xml", faAnyFile, sr) = 0 atunci
repeta
ExportFile:= TStringList.Create;
softbase:= LoadSTDSoftware(Pchar(CurDir+sr.Name));
pentru i:= 0 la softbase.InstalledSoftware.source.software.Count - 1 do
ExportFile.Add(softbase.InstalledSoftware.source.software[i].DisplayName);
ExportFile.Sort;
ExportFile.SaveToFile(CurDir + softbase.InstalledSoftware.Source.servername+".txt");
ExportFile.Free;
până la FindNext(sr) 0;
Sfârşit;
ÎNCEPE
Application.Initialize;
CovertXML2Text;
Sfârşit.
Ca urmare, am avut câte un fișier text pentru fiecare computer din rețea, care conținea o listă de software instalat.
Simt că acest cod necesită o explicație. De exemplu, de ce am folosit modulul Forms într-o aplicație consolă și am apelat procedura Application.Initialize;?
De fapt, este simplu - este un mic hack care vă permite să utilizați XML Data Binding într-o aplicație de consolă. Pentru că a refuzat cu încăpățânare să inițialeze clasa pentru lucrul cu XML. Nu mi-am dat seama încă motivele reale - timpul a fost important astăzi, am petrecut deja 4 din 5 minute luptând cu această eroare. :) Cred că mă voi ocupa de această problemă mai târziu și voi scrie care este motivul real.
Ciudată clasă softbase a fost creată pe baza unui fișier XML - acesta era numele elementului rădăcină și softbase.InstalledSoftware.source.software[i].DisplayName - pur și simplu navigați prin elementele imbricate la cel dorit și obțineți valoarea acestuia.
Acesta este de fapt cum arată unul dintre cele mai multe moduri rapide lucrul cu XML în Delphi.
XML este din ce în ce mai folosit pentru a stoca informații și a le schimba între aplicații și site-uri web. Multe aplicații folosesc acest limbaj ca limbaj de bază pentru stocarea datelor, în timp ce altele îl folosesc pentru exportul și importarea datelor XML. Aceasta înseamnă că este timpul ca dezvoltatorii să se gândească la modul în care pot folosi datele XML în propriile aplicații.
În acest articol ne vom uita la documentul XML Model obiect(DOM) și implementarea acesteia de către Microsoft - Microsoft XML DOM.
XML DOM este un model de obiecte care oferă dezvoltatorului obiecte pentru încărcarea și procesarea fișierelor XML. Modelul obiect constă din următoarele obiecte principale: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap și XMLDOMParseError. Fiecare dintre aceste obiecte (cu excepția XMLDOMParseError) conține proprietăți și metode care vă permit să obțineți informații despre obiect, să manipulați valorile și structura obiectului și să navigați prin structura documentului XML.
Să ne uităm la principalele obiecte XML DOM și să dăm câteva exemple de utilizare a acestora în Borland Delphi.
Utilizarea XML DOM în Borland Delphi
Pentru a utiliza Microsoft XML DOM în aplicațiile Delphi, trebuie să conectați biblioteca de tip corespunzătoare la proiect. Pentru a face acest lucru, executăm comanda Project | Import Type Library și în caseta de dialog Import Type Library, selectați biblioteca Microsoft XML versiunea 2.0 (Versiunea 2.0), care se află de obicei în fișierul Windows\System\MSXML.DLL
După ce facem clic pe butonul Create Unit, va fi creat modulul de interfață MSXML_TLB, care ne va permite să folosim obiecte XML DOM: DOMDocument, XMLDocument, XMLHTTPRequest și o serie de altele implementate în biblioteca MSXML.DLL. O referință la modulul MSXML_TLB trebuie să fie listată în lista Utilizări.
Dispozitiv XML DOM
Document Object Model reprezintă un document XML ca o structură arborescentă constând din ramuri. Interfețele de programare XML DOM permit aplicațiilor să navigheze în arborele de documente și să manipuleze ramurile acestuia. Fiecare ramură poate avea un anumit tip (DOMNodeType), în funcție de care sunt determinate ramurile părinte și fii. În majoritatea documentelor XML veți găsi ramuri precum element, atribut și text. Atributele sunt un tip special de ramură și nu sunt ramuri copil. Atributele sunt folosite pentru a gestiona metode speciale, furnizat de obiectele XML DOM.
Pe lângă implementarea interfețelor recomandate de World Wide Web Consortium (W3C), Microsoft XML DOM conține metode care acceptă XSL, modele XSL, spații de nume și tipuri de date. De exemplu, metoda SelectNodes vă permite să utilizați sintaxa modelului XSL pentru a găsi ramuri într-un context specific, iar metoda TransformNode acceptă utilizarea XSL pentru a efectua transformări.
Testează documentul XML
Ca exemplu de document XML, să luăm un director de CD-ROM-uri muzicale, care are următoarea structură:
Acum suntem gata să începem să ne uităm la modelul de obiect XML DOM, pe care îl vom începe cu obiectul XMLDOMDocument.
Document XML - obiect XMLDOMDocument
Lucrul cu un document XML începe cu încărcarea acestuia. Pentru a face acest lucru, folosim metoda Load, care are un singur parametru care indică adresa URL a documentului de încărcat. La încărcarea fișierelor de pe un disc local, este specificat doar numele complet al fișierului (protocolul fișier:/// poate fi omis în acest caz). Dacă documentul XML este stocat ca șir, ar trebui să utilizați metoda LoadXML pentru a încărca documentul.
Pentru a controla modul în care este încărcat documentul (sincron sau asincron), utilizați proprietatea Async. În mod implicit, această proprietate este setată la True, ceea ce indică faptul că documentul este încărcat asincron și controlul este returnat aplicației înainte ca documentul să fie încărcat complet. În caz contrar, documentul este încărcat sincron, iar apoi trebuie să verificați valoarea proprietății ReadyState pentru a afla dacă documentul s-a încărcat sau nu. De asemenea, puteți crea un handler de evenimente OnReadyStateChange care va primi control atunci când valoarea proprietății ReadyState se schimbă.
Următoarele arată cum să încărcați un document XML utilizând metoda Load:
Utilizează ... MSXML_TLB ... procedura TForm1.Button1Click(Sender: TObject); var XMLDoc: IXMLDOMDocument; începe XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // // Iată codul care manipulează // documentul XML și ramurile acestuia // XMLDoc:= Nil; Sfârşit;
Odată ce documentul este încărcat, putem accesa proprietățile acestuia. Astfel, proprietatea NodeName va conține valoarea #document, proprietatea NodeTypeString va conține documentul cu valoare, iar proprietatea URL va conține valoarea fișier:///C:/DATA/DATA.xml.
Eroare de manipulare
De un interes deosebit sunt proprietățile asociate procesării documentului atunci când este încărcat. Astfel, proprietatea ParseError returnează un obiect XMLDOMParseError care conține informații despre o eroare care a apărut în timpul procesării documentului.
Pentru a scrie un handler de erori, puteți adăuga următorul cod:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load('C:\DATA\DATA.xml'); XMLError:= XMLDoc.ParseError; Dacă XMLError.ErrorCode<>0 Apoi // // Aici ne ocupăm de eroare // Else Memo1.Lines.Add(XMLDoc.XML); ... XMLDoc:= Nil;
Pentru a vedea ce informații sunt returnate în cazul unei erori, să schimbăm următoarea intrare din director:
îndepărtarea elementului de închidere
Acum să scriem cod care returnează valorile proprietăților obiectului XMLDOMParseError:
XMLError:= XMLDoc.ParseError; Dacă XMLError.ErrorCode<>0 Apoi, cu XMLError, Memo1.Lines începe Add(‘File:’ + URL); Add('Cod: ' + IntToStr(ErrorCode)); Add(‘Eroare: ‘+ Motiv); Add(‘Text: ‘+SrcText); Add('Linie: ' + IntToStr(Line)); Add(‘Poziție: ‘ + IntToStr(LinePos)); end Else Memo1.Lines.Add(XMLDoc.XML); Sfârşit;
și să rulăm aplicația noastră. Ca urmare, primim următoarele informații despre eroare.
După cum puteți vedea din exemplul de mai sus, informațiile returnate de obiectul XMLDOMParseError sunt destul de suficiente pentru a localiza eroarea și a înțelege motivul apariției acesteia.
Acum să restabilim elementul de închidere
Accesarea arborelui documentelor
Pentru a accesa un arbore de document, puteți fie să obțineți elementul rădăcină și apoi să iterați prin ramurile sale secundare, fie să găsiți o anumită ramură. În primul caz, obținem elementul rădăcină prin proprietatea DocumentElement, care returnează un obiect de tip XMLDOMNode. Următoarele arată cum să utilizați proprietatea DocumentElement pentru a obține conținutul fiecărui element copil:
Var Nod: IXMLDOMNode; Rădăcină: IXMLDOMElement; I: întreg; ... Root:= XMLDoc.DocumentElement; Pentru I:= 0 la Root.ChildNodes.Length-1 face Begin Node:= Root.ChildNodes.Item[I]; Memo1.Lines.Add(Nod.Text); Sfârşit;
Pentru documentul nostru XML vom obține următorul text.
Dacă suntem interesați de o anumită ramură sau de o ramură sub prima ramură copil, putem folosi fie metoda NodeFromID, fie metoda GetElementByTagName a obiectului XMLDOMDocument.
Metoda NodeFromID necesită un identificator unic definit în Schema XML sau Definiția tipului de document (DTD) și returnează o ramură cu acel identificator.
Metoda GetElementByTagName necesită specificarea unui șir cu un anumit element (etichetă) și returnează toate ramurile cu acest element. Mai jos este cum să folosiți această metodă pentru a găsi toți artiștii din directorul nostru CD-ROM:
Noduri: IXMLDOMNodeList; Nod: IXMLDOMNode; ... Noduri:= XMLDoc.GetElementsByTagName('ARTIST'); Pentru I:= 0 la Noduri.Lungime-1 nu Începe Nodul:= Noduri.Element[I]; Memo1.Lines.Add(Nod.Text); Sfârşit;
Pentru documentul nostru XML vom obține următorul text
Rețineți că metoda SelectNodes a obiectului XMLDOMNode oferă o modalitate mai flexibilă de a accesa ramurile documentului. Dar mai multe despre asta mai jos.
Ramura document - obiect XMLDOMNode
Un obiect XMLDOMNode reprezintă o ramură a documentului. Am întâlnit deja acest obiect când am primit elementul rădăcină al documentului:
Root:= XMLDoc.DocumentElement;
Pentru a obține informații despre ramura unui document XML, puteți utiliza proprietățile obiectului XMLDOMNode (Tabelul 1).
Pentru a accesa datele stocate într-o ramură, utilizați de obicei fie proprietatea NodeValue (disponibilă pentru atribute, ramuri de text, comentarii, instrucțiuni de procesare și secțiuni CDATA), proprietatea Text, care returnează conținutul text al ramurii, fie proprietatea NodeTypedValue . Acesta din urmă, însă, poate fi folosit doar pentru ramuri cu elemente tipizate.
Navigarea în arborele documentelor
Obiectul XMLDOMNode oferă multe modalități de a naviga în arborele documentului. De exemplu, pentru a accesa ramura părinte se folosește proprietatea ParentNode (tip XMLDOMNode), ramurile copil sunt accesate prin proprietățile ChildNodes (tip XMLDOMNodeList), FirstChild și LastChild (tip XMLDOMNode) etc. Proprietatea OwnerDocument returnează un obiect de tip XMLDOMDocument care identifică documentul XML însuși. Proprietățile enumerate mai sus vă permit să navigați cu ușurință în arborele documentului.
Acum să trecem prin toate ramurile documentului XML:
Root:= XMLDoc.DocumentElement; Pentru I:= 0 la Root.ChildNodes.Length-1 face Begin Node:= Root.ChildNodes.Item[I]; Dacă Node.HasChildNodes, atunci GetChilds(Node,0); Sfârşit;
După cum sa menționat mai sus, SelectNodes-ul obiectului XMLDOMNode oferă o modalitate mai flexibilă de a accesa ramurile documentelor. În plus, există o metodă SelectSingleNode care returnează doar prima ramură a documentului. Ambele metode vă permit să specificați șabloane XSL pentru a căuta ramuri.
Să parcurgem procesul de utilizare a metodei SelectNodes pentru a prelua toate ramurile care au o ramură CD și o subramură PRICE:
Root:= XMLDoc.DocumentElement; Noduri:= Root.SelectNodes('CD/PRICE');
Toate sub-ramurile PRICE ale sucursalei CD vor fi plasate în colecția Nodes. Vom reveni la discuția despre șabloanele XSL puțin mai târziu.
Manipularea ramurilor copiilor
Pentru a manipula ramurile copil, putem folosi metodele obiectului XMLDOMNode (Tabelul 2).
Pentru a șterge complet intrarea pentru primul disc, trebuie să rulați următorul cod:
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Obține elementul rădăcină Root:= XMLDoc.DocumentElement; Nod:= Rădăcină; // Îndepărtați prima ramură copil Node.RemoveChild(Node.FirstChild);
Rețineți că în acest exemplu ștergem prima ramură copil. Cum să eliminați primul element al primei ramuri copil este prezentat mai jos:
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Obține elementul rădăcină Root:= XMLDoc.DocumentElement; // și prima ramură copil Node:= Root.FirstChild; // Îndepărtați prima ramură copil Node.RemoveChild(Node.FirstChild);
În exemplul de mai sus, nu am șters prima ramură
Acum să adăugăm o nouă ramură. Mai jos este codul care arată cum să adăugați o nouă intrare CD-ROM muzicală:
Var NewNode: IXMLDOMNode; Copil: IXMLDOMNode; ... // Creați o nouă ramură -
Codul de mai sus arată următoarea secvență de pași pentru a adăuga o nouă ramură:
- Crearea unei noi ramuri folosind metoda CreateNode:
- crearea unui element folosind metoda CreateNode;
- adăugarea unui element la o ramură folosind metoda AppendChild;
- setarea valorii elementului prin proprietatea Text;
- ...repetați pentru toate elementele.
- Adăugarea unei noi ramuri la un document utilizând metoda AppendChild.
Amintiți-vă că metoda AppendChild adaugă o ramură la sfârșitul arborelui. Pentru a adăuga o ramură într-o anumită locație din arbore, trebuie să utilizați metoda InsertBefore.
Set de ramuri - obiect XMLDOMNodeList
Obiectul XMLNodeList conține o listă de ramuri care pot fi construite folosind metodele SelectNodes sau GetElementsByTagName sau obținute din proprietatea ChildNodes.
Am analizat deja utilizarea acestui obiect în exemplul dat în secțiunea „Navigarea în arborele documentelor”. Vă prezentăm aici câteva remarci teoretice.
Numărul de ramuri din listă poate fi obținut ca valoare a proprietății Length. Ramurile au indici de la 0 la Lungimea-1, iar fiecare ramură individuală este accesibilă prin elementul matrice Item cu indexul corespunzător.
Navigarea printr-o listă de ramuri se poate face și folosind metoda NextNode, care returnează următoarea ramură din listă, sau Nil dacă ramura curentă este ultima. Pentru a reveni la începutul listei, apelați metoda Reset.
Crearea și salvarea documentelor
Până acum am analizat cum puteți adăuga ramuri și elemente la documentele XML existente. Acum să creăm un document XML din mers. În primul rând, permiteți-ne să vă reamintim că un document poate fi încărcat nu numai dintr-un URL, ci și dintr-un șir obișnuit. Următoarele arată cum să creați un element rădăcină, care poate fi apoi folosit pentru a construi dinamic alte elemente (pe care le-am acoperit deja în secțiunea Manipularea ramurilor copiilor):
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; S: WideString; ... S:= ‘
După construirea documentului XML, îl vom salva într-un fișier folosind metoda Save. De exemplu:
XMLDoc.Save('C:\DATA\NEWCD.XML');
Pe lângă salvarea într-un fișier, metoda Salvare vă permite să salvați documentul XML într-un nou obiect XMLDOMDocument. În acest caz, documentul este complet procesat și, ca urmare, structura și sintaxa acestuia sunt verificate. Următoarele arată cum să salvați un document într-un alt obiect:
Procedura TForm1.Button2Click(Expeditor: TObject); var XMLDoc2: IXMLDOMDocument; începe XMLDoc2:= CoDOMDocument.Create; XMLDoc.Save(XMLDoc2); Memo2.Lines.Add(XMLDoc2.XML); ... XMLDoc2:= Nil; Sfârşit;
În cele din urmă, rețineți că metoda Salvare vă permite, de asemenea, să salvați un document XML pe alte obiecte COM care acceptă interfețele IStream, IPersistStream sau IPersistStreamInit.
Utilizarea șabloanelor XSL
Când discutăm despre metoda SelectNodes a obiectului XMLDOMNode, am menționat că oferă o modalitate mai flexibilă de a accesa ramurile documentelor. Flexibilitatea constă în faptul că puteți specifica un șablon XSL ca criteriu de selectare a ramurilor. Astfel de șabloane oferă un mecanism puternic pentru căutarea informațiilor în documente XML. De exemplu, pentru a obține o listă cu toate titlurile CD-ROM-urilor muzicale din catalogul nostru, puteți rula următoarea interogare:
Pentru a afla ce discuri ale artiștilor au fost lansate în SUA, cererea se formează după cum urmează:
Noduri:= Root.SelectNodes('CD/ARTIST');
Următoarele arată cum să găsiți prima unitate din director:
Noduri:= Root.SelectNodes('CD/TITLE');
Și în ultimul rând:
Noduri:= Root.SelectNodes('CD/TITLE');
Pentru a găsi CD-uri Bob Dylan, puteți rula următoarea interogare:
Noduri:= Root.SelectNodes(‘CD[$any$ ARTIST= ”Bob Dylan”]/TITLE’);
și pentru a obține o listă de discuri lansate după 1985, rulăm următoarea interogare:
Noduri:= Root.SelectNodes('CD/TITLE');
O discuție mai detaliată despre sintaxa XSL necesită o postare separată. Pentru a intriga cititorii și pentru a încuraja cercetările ulterioare, voi da doar un mic exemplu de posibile utilizări ale XSL. Să presupunem că trebuie să ne transformăm catalogul într-un tabel HTML obișnuit. Folosind metode tradiționale, trebuie să trecem prin toate ramurile arborelui și să formăm etichetele corespunzătoare pentru fiecare element primit.
Folosind XSL, pur și simplu creăm un șablon (sau o foaie de stil) în care indicăm ce trebuie convertit și cum. Apoi suprapunem acest șablon pe directorul nostru - și am terminat: avem textul unui șablon XSL care convertește directorul într-un tabel (Listing 2).
Codul pentru suprapunerea șablonului XSL în directorul nostru arată astfel:
Procedura TForm1.Button2Click(Expeditor: TObject); var XSLDoc: IXMLDOMDocument; începe XSLDoc:= CoDOMDocument.Create; XSLDoc.Load('C:\DATA\DATA.xsl'); Memo2.Text:= XMLDoc.TransformNode(XSLDoc); XSLDoc:= Nil; Sfârşit;
Încheind discuția noastră despre XSL, trebuie spus că în prezent acest limbaj este utilizat activ pentru transformarea între diverse documente XML, precum și pentru formatarea documentelor.
Concluzie
Din motive evidente, este imposibil să revizuiți toate obiectele Microsoft XML DOM și să furnizați exemple de utilizare a acestora într-un articol. Aici am atins doar problemele de bază ale utilizării XML DOM în aplicații. În tabel Figura 3 prezintă toate obiectele implementate în Microsoft XML DOM.
ComputerPress 12"2000
XML este din ce în ce mai folosit pentru a stoca informații și a le schimba între aplicații și site-uri web. Multe aplicații folosesc acest limbaj ca limbaj de bază pentru stocarea datelor, în timp ce altele îl folosesc pentru exportul și importarea datelor XML. Aceasta înseamnă că este timpul ca dezvoltatorii să se gândească la modul în care pot folosi datele XML în propriile aplicații.
În acest articol ne vom uita la XML Document Object Model (DOM) și implementarea acestuia de către Microsoft - Microsoft XML DOM.
XML DOM este un model de obiecte care oferă dezvoltatorului obiecte pentru încărcarea și procesarea fișierelor XML. Modelul obiect constă din următoarele obiecte principale: XMLDOMDocument, XMLDOMNodeList, XMLDOMNode, XMLDOMNamedNodeMap și XMLDOMParseError. Fiecare dintre aceste obiecte (cu excepția XMLDOMParseError) conține proprietăți și metode care vă permit să obțineți informații despre obiect, să manipulați valorile și structura obiectului și să navigați prin structura documentului XML.
Să ne uităm la principalele obiecte XML DOM și să dăm câteva exemple de utilizare a acestora în Borland Delphi.
Utilizarea XML DOM în Borland Delphi
Pentru a utiliza Microsoft XML DOM în aplicațiile Delphi, trebuie să conectați biblioteca de tip corespunzătoare la proiect. Pentru a face acest lucru, executăm comanda Project | Import Type Library și în caseta de dialog Import Type Library, selectați biblioteca Microsoft XML versiunea 2.0 (Versiunea 2.0), care se află de obicei în fișierul Windows\System\MSXML.DLL
După ce facem clic pe butonul Create Unit, va fi creat modulul de interfață MSXML_TLB, care ne va permite să folosim obiecte XML DOM: DOMDocument, XMLDocument, XMLHTTPRequest și o serie de altele implementate în biblioteca MSXML.DLL. O referință la modulul MSXML_TLB trebuie să fie listată în lista Utilizări.
Dispozitiv XML DOM
Document Object Model reprezintă un document XML ca o structură arborescentă constând din ramuri. Interfețele de programare XML DOM permit aplicațiilor să navigheze în arborele de documente și să manipuleze ramurile acestuia. Fiecare ramură poate avea un anumit tip (DOMNodeType), în funcție de care sunt determinate ramurile părinte și fii. În majoritatea documentelor XML veți găsi ramuri precum element, atribut și text. Atributele sunt un tip special de ramură și nu sunt ramuri copil. Atributele sunt manipulate folosind metode speciale oferite de obiectele XML DOM.
Pe lângă implementarea interfețelor recomandate de World Wide Web Consortium (W3C), Microsoft XML DOM conține metode care acceptă XSL, modele XSL, spații de nume și tipuri de date. De exemplu, metoda SelectNodes vă permite să utilizați sintaxa modelului XSL pentru a găsi ramuri într-un context specific, iar metoda TransformNode acceptă utilizarea XSL pentru a efectua transformări.
Testează documentul XML
Ca exemplu de document XML, să luăm un director de CD-ROM-uri muzicale, care are următoarea structură:
Acum suntem gata să începem să ne uităm la modelul de obiect XML DOM, pe care îl vom începe cu obiectul XMLDOMDocument.
Document XML - obiect XMLDOMDocument
Lucrul cu un document XML începe cu încărcarea acestuia. Pentru a face acest lucru, folosim metoda Load, care are un singur parametru care indică adresa URL a documentului de încărcat. La încărcarea fișierelor de pe un disc local, este specificat doar numele complet al fișierului (protocolul fișier:/// poate fi omis în acest caz). Dacă documentul XML este stocat ca șir, ar trebui să utilizați metoda LoadXML pentru a încărca documentul.
Pentru a controla modul în care este încărcat documentul (sincron sau asincron), utilizați proprietatea Async. În mod implicit, această proprietate este setată la True, ceea ce indică faptul că documentul este încărcat asincron și controlul este returnat aplicației înainte ca documentul să fie încărcat complet. În caz contrar, documentul este încărcat sincron, iar apoi trebuie să verificați valoarea proprietății ReadyState pentru a afla dacă documentul s-a încărcat sau nu. De asemenea, puteți crea un handler de evenimente OnReadyStateChange care va primi control atunci când valoarea proprietății ReadyState se schimbă.
Următoarele arată cum să încărcați un document XML utilizând metoda Load:
Utilizează ... MSXML_TLB ... procedura TForm1.Button1Click(Sender: TObject); var XMLDoc: IXMLDOMDocument; începe XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // // Iată codul care manipulează // documentul XML și ramurile acestuia // XMLDoc:= Nil; Sfârşit;
Odată ce documentul este încărcat, putem accesa proprietățile acestuia. Astfel, proprietatea NodeName va conține valoarea #document, proprietatea NodeTypeString va conține documentul cu valoare, iar proprietatea URL va conține valoarea fișier:///C:/DATA/DATA.xml.
Eroare de manipulare
De un interes deosebit sunt proprietățile asociate procesării documentului atunci când este încărcat. Astfel, proprietatea ParseError returnează un obiect XMLDOMParseError care conține informații despre o eroare care a apărut în timpul procesării documentului.
Pentru a scrie un handler de erori, puteți adăuga următorul cod:
Var XMLError: IXMLDOMParseError; ... XMLDoc.Load('C:\DATA\DATA.xml'); XMLError:= XMLDoc.ParseError; Dacă XMLError.ErrorCode<>0 Apoi // // Aici ne ocupăm de eroare // Else Memo1.Lines.Add(XMLDoc.XML); ... XMLDoc:= Nil;
Pentru a vedea ce informații sunt returnate în cazul unei erori, să schimbăm următoarea intrare din director:
îndepărtarea elementului de închidere
Acum să scriem cod care returnează valorile proprietăților obiectului XMLDOMParseError:
XMLError:= XMLDoc.ParseError; Dacă XMLError.ErrorCode<>0 Apoi, cu XMLError, Memo1.Lines începe Add(‘File:’ + URL); Add('Cod: ' + IntToStr(ErrorCode)); Add(‘Eroare: ‘+ Motiv); Add(‘Text: ‘+SrcText); Add('Linie: ' + IntToStr(Line)); Add(‘Poziție: ‘ + IntToStr(LinePos)); end Else Memo1.Lines.Add(XMLDoc.XML); Sfârşit;
și să rulăm aplicația noastră. Ca urmare, primim următoarele informații despre eroare.
După cum puteți vedea din exemplul de mai sus, informațiile returnate de obiectul XMLDOMParseError sunt destul de suficiente pentru a localiza eroarea și a înțelege motivul apariției acesteia.
Acum să restabilim elementul de închidere
Accesarea arborelui documentelor
Pentru a accesa un arbore de document, puteți fie să obțineți elementul rădăcină și apoi să iterați prin ramurile sale secundare, fie să găsiți o anumită ramură. În primul caz, obținem elementul rădăcină prin proprietatea DocumentElement, care returnează un obiect de tip XMLDOMNode. Următoarele arată cum să utilizați proprietatea DocumentElement pentru a obține conținutul fiecărui element copil:
Var Nod: IXMLDOMNode; Rădăcină: IXMLDOMElement; I: întreg; ... Root:= XMLDoc.DocumentElement; Pentru I:= 0 la Root.ChildNodes.Length-1 face Begin Node:= Root.ChildNodes.Item[I]; Memo1.Lines.Add(Nod.Text); Sfârşit;
Pentru documentul nostru XML vom obține următorul text.
Dacă suntem interesați de o anumită ramură sau de o ramură sub prima ramură copil, putem folosi fie metoda NodeFromID, fie metoda GetElementByTagName a obiectului XMLDOMDocument.
Metoda NodeFromID necesită un identificator unic definit în Schema XML sau Definiția tipului de document (DTD) și returnează o ramură cu acel identificator.
Metoda GetElementByTagName necesită specificarea unui șir cu un anumit element (etichetă) și returnează toate ramurile cu acest element. Mai jos este cum să folosiți această metodă pentru a găsi toți artiștii din directorul nostru CD-ROM:
Noduri: IXMLDOMNodeList; Nod: IXMLDOMNode; ... Noduri:= XMLDoc.GetElementsByTagName('ARTIST'); Pentru I:= 0 la Noduri.Lungime-1 nu Începe Nodul:= Noduri.Element[I]; Memo1.Lines.Add(Nod.Text); Sfârşit;
Pentru documentul nostru XML vom obține următorul text
Rețineți că metoda SelectNodes a obiectului XMLDOMNode oferă o modalitate mai flexibilă de a accesa ramurile documentului. Dar mai multe despre asta mai jos.
Ramura document - obiect XMLDOMNode
Un obiect XMLDOMNode reprezintă o ramură a documentului. Am întâlnit deja acest obiect când am primit elementul rădăcină al documentului:
Root:= XMLDoc.DocumentElement;
Pentru a obține informații despre ramura unui document XML, puteți utiliza proprietățile obiectului XMLDOMNode (Tabelul 1).
Pentru a accesa datele stocate într-o ramură, utilizați de obicei fie proprietatea NodeValue (disponibilă pentru atribute, ramuri de text, comentarii, instrucțiuni de procesare și secțiuni CDATA), proprietatea Text, care returnează conținutul text al ramurii, fie proprietatea NodeTypedValue . Acesta din urmă, însă, poate fi folosit doar pentru ramuri cu elemente tipizate.
Navigarea în arborele documentelor
Obiectul XMLDOMNode oferă multe modalități de a naviga în arborele documentului. De exemplu, pentru a accesa ramura părinte se folosește proprietatea ParentNode (tip XMLDOMNode), ramurile copil sunt accesate prin proprietățile ChildNodes (tip XMLDOMNodeList), FirstChild și LastChild (tip XMLDOMNode) etc. Proprietatea OwnerDocument returnează un obiect de tip XMLDOMDocument care identifică documentul XML însuși. Proprietățile enumerate mai sus vă permit să navigați cu ușurință în arborele documentului.
Acum să trecem prin toate ramurile documentului XML:
Root:= XMLDoc.DocumentElement; Pentru I:= 0 la Root.ChildNodes.Length-1 face Begin Node:= Root.ChildNodes.Item[I]; Dacă Node.HasChildNodes, atunci GetChilds(Node,0); Sfârşit;
După cum sa menționat mai sus, SelectNodes-ul obiectului XMLDOMNode oferă o modalitate mai flexibilă de a accesa ramurile documentelor. În plus, există o metodă SelectSingleNode care returnează doar prima ramură a documentului. Ambele metode vă permit să specificați șabloane XSL pentru a căuta ramuri.
Să parcurgem procesul de utilizare a metodei SelectNodes pentru a prelua toate ramurile care au o ramură CD și o subramură PRICE:
Root:= XMLDoc.DocumentElement; Noduri:= Root.SelectNodes('CD/PRICE');
Toate sub-ramurile PRICE ale sucursalei CD vor fi plasate în colecția Nodes. Vom reveni la discuția despre șabloanele XSL puțin mai târziu.
Manipularea ramurilor copiilor
Pentru a manipula ramurile copil, putem folosi metodele obiectului XMLDOMNode (Tabelul 2).
Pentru a șterge complet intrarea pentru primul disc, trebuie să rulați următorul cod:
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Obține elementul rădăcină Root:= XMLDoc.DocumentElement; Nod:= Rădăcină; // Îndepărtați prima ramură copil Node.RemoveChild(Node.FirstChild);
Rețineți că în acest exemplu ștergem prima ramură copil. Cum să eliminați primul element al primei ramuri copil este prezentat mai jos:
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; XMLDoc:= CoDOMDocument.Create; XMLDoc.Async:= False; XMLDoc.Load('C:\DATA\DATA.xml'); // Obține elementul rădăcină Root:= XMLDoc.DocumentElement; // și prima ramură copil Node:= Root.FirstChild; // Îndepărtați prima ramură copil Node.RemoveChild(Node.FirstChild);
În exemplul de mai sus, nu am șters prima ramură
Acum să adăugăm o nouă ramură. Mai jos este codul care arată cum să adăugați o nouă intrare CD-ROM muzicală:
Var NewNode: IXMLDOMNode; Copil: IXMLDOMNode; ... // Creați o nouă ramură -
Codul de mai sus arată următoarea secvență de pași pentru a adăuga o nouă ramură:
- Crearea unei noi ramuri folosind metoda CreateNode:
- crearea unui element folosind metoda CreateNode;
- adăugarea unui element la o ramură folosind metoda AppendChild;
- setarea valorii elementului prin proprietatea Text;
- ...repetați pentru toate elementele.
- Adăugarea unei noi ramuri la un document utilizând metoda AppendChild.
Amintiți-vă că metoda AppendChild adaugă o ramură la sfârșitul arborelui. Pentru a adăuga o ramură într-o anumită locație din arbore, trebuie să utilizați metoda InsertBefore.
Set de ramuri - obiect XMLDOMNodeList
Obiectul XMLNodeList conține o listă de ramuri care pot fi construite folosind metodele SelectNodes sau GetElementsByTagName sau obținute din proprietatea ChildNodes.
Am analizat deja utilizarea acestui obiect în exemplul dat în secțiunea „Navigarea în arborele documentelor”. Vă prezentăm aici câteva remarci teoretice.
Numărul de ramuri din listă poate fi obținut ca valoare a proprietății Length. Ramurile au indici de la 0 la Lungimea-1, iar fiecare ramură individuală este accesibilă prin elementul matrice Item cu indexul corespunzător.
Navigarea printr-o listă de ramuri se poate face și folosind metoda NextNode, care returnează următoarea ramură din listă, sau Nil dacă ramura curentă este ultima. Pentru a reveni la începutul listei, apelați metoda Reset.
Crearea și salvarea documentelor
Până acum am analizat cum puteți adăuga ramuri și elemente la documentele XML existente. Acum să creăm un document XML din mers. În primul rând, permiteți-ne să vă reamintim că un document poate fi încărcat nu numai dintr-un URL, ci și dintr-un șir obișnuit. Următoarele arată cum să creați un element rădăcină, care poate fi apoi folosit pentru a construi dinamic alte elemente (pe care le-am acoperit deja în secțiunea Manipularea ramurilor copiilor):
Var XMLDoc: IXMLDOMDocument; Rădăcină: IXMLDOMNode; Nod: IXMLDOMNode; S: WideString; ... S:= ‘
După construirea documentului XML, îl vom salva într-un fișier folosind metoda Save. De exemplu:
XMLDoc.Save('C:\DATA\NEWCD.XML');
Pe lângă salvarea într-un fișier, metoda Salvare vă permite să salvați documentul XML într-un nou obiect XMLDOMDocument. În acest caz, documentul este complet procesat și, ca urmare, structura și sintaxa acestuia sunt verificate. Următoarele arată cum să salvați un document într-un alt obiect:
Procedura TForm1.Button2Click(Expeditor: TObject); var XMLDoc2: IXMLDOMDocument; începe XMLDoc2:= CoDOMDocument.Create; XMLDoc.Save(XMLDoc2); Memo2.Lines.Add(XMLDoc2.XML); ... XMLDoc2:= Nil; Sfârşit;
În cele din urmă, rețineți că metoda Salvare vă permite, de asemenea, să salvați un document XML pe alte obiecte COM care acceptă interfețele IStream, IPersistStream sau IPersistStreamInit.
Utilizarea șabloanelor XSL
Când discutăm despre metoda SelectNodes a obiectului XMLDOMNode, am menționat că oferă o modalitate mai flexibilă de a accesa ramurile documentelor. Flexibilitatea constă în faptul că puteți specifica un șablon XSL ca criteriu de selectare a ramurilor. Astfel de șabloane oferă un mecanism puternic pentru căutarea informațiilor în documente XML. De exemplu, pentru a obține o listă cu toate titlurile CD-ROM-urilor muzicale din catalogul nostru, puteți rula următoarea interogare:
Pentru a afla ce discuri ale artiștilor au fost lansate în SUA, cererea se formează după cum urmează:
Noduri:= Root.SelectNodes('CD/ARTIST');
Următoarele arată cum să găsiți prima unitate din director:
Noduri:= Root.SelectNodes('CD/TITLE');
Și în ultimul rând:
Noduri:= Root.SelectNodes('CD/TITLE');
Pentru a găsi CD-uri Bob Dylan, puteți rula următoarea interogare:
Noduri:= Root.SelectNodes(‘CD[$any$ ARTIST= ”Bob Dylan”]/TITLE’);
și pentru a obține o listă de discuri lansate după 1985, rulăm următoarea interogare:
Noduri:= Root.SelectNodes('CD/TITLE');
O discuție mai detaliată despre sintaxa XSL necesită o postare separată. Pentru a intriga cititorii și pentru a încuraja cercetările ulterioare, voi da doar un mic exemplu de posibile utilizări ale XSL. Să presupunem că trebuie să ne transformăm catalogul într-un tabel HTML obișnuit. Folosind metode tradiționale, trebuie să trecem prin toate ramurile arborelui și să formăm etichetele corespunzătoare pentru fiecare element primit.
Folosind XSL, pur și simplu creăm un șablon (sau o foaie de stil) în care indicăm ce trebuie convertit și cum. Apoi suprapunem acest șablon pe directorul nostru - și am terminat: avem textul unui șablon XSL care convertește directorul într-un tabel (Listing 2).
Codul pentru suprapunerea șablonului XSL în directorul nostru arată astfel:
Procedura TForm1.Button2Click(Expeditor: TObject); var XSLDoc: IXMLDOMDocument; începe XSLDoc:= CoDOMDocument.Create; XSLDoc.Load('C:\DATA\DATA.xsl'); Memo2.Text:= XMLDoc.TransformNode(XSLDoc); XSLDoc:= Nil; Sfârşit;
Încheind discuția noastră despre XSL, trebuie spus că în prezent acest limbaj este utilizat activ pentru transformarea între diverse documente XML, precum și pentru formatarea documentelor.
Concluzie
Din motive evidente, este imposibil să revizuiți toate obiectele Microsoft XML DOM și să furnizați exemple de utilizare a acestora într-un articol. Aici am atins doar problemele de bază ale utilizării XML DOM în aplicații. În tabel Figura 3 prezintă toate obiectele implementate în Microsoft XML DOM.
ComputerPress 12"2000
Bună ziua tuturor! Am scris pe Matlab câțiva ani, apoi am simțit nevoia de a scrie un program în Delphi.
Trebuie să învăț cum să lucrez cu documente xml. Lucrez în RAD Stiduo XE3. Există o componentă TXMLDocument, probabil cunoscută de mulți programatori Delphi. Se pare că poate face multe. Dar problema este că nu există o documentație clară și o descriere pentru aceasta. Ajutorul în RAD Studio este un gunoi, deoarece acolo nu există informații normale; doar informații limitate despre unele metode și proceduri împrăștiate pe pagini (fără exemple sau descrieri adecvate). Am căutat pe tot internetul. Am găsit doar subiecte pe forumuri cu soluții la probleme specifice, unde trebuie să mai ghiciți încă o oră ce face cutare sau cutare linie când accesați un fișier xml.
Am nevoie de îndrumare cu privire la principalele funcții, proceduri și metode utilizate atunci când lucrez cu xml. Manual, manual, descriere. Sau cel puțin „xml în Delphi pentru manechini”. De exemplu:
Pentru a deschide un fișier xml, utilizați metoda XMLDocument1.LoadFromFile("filemane.xml"), unde nume fișier este numele fișierului.
Variabila nodelist de tip IXMLNode este utilizată pentru a stoca o listă elemente copil. Pentru a defini această listă, utilizați metoda Xmldocument1.DocumentElement (unde XMLDocument1 este fișierul xml care este examinat).
Pentru a interoga conținutul elementului copil "element1" se folosește metoda XMLDocument1.DocumentElement.ChildNodes["element1"].Text....
și în acest spirit în continuare toate metodele, procedurile și tipurile de date utilizate.
Unde pot găsi manuale/descrieri similare? Cine poate ajuta?
Dacă aveți nevoie de o sarcină specifică, o voi descrie.
Există un document xml ca:
Un text
Un text de eroare
Alt text de eroare
În codul programului avem:
var
...
părinte, copil1: IXMLNode;
ÎNCEPE
XMLDocument1.LoadFromFile("f:\filename.x ml");
XMLDocument1.Active:=true;
.
.
Sfârşit
Ce trebuie să înveți să faci:
(Îmi cer scuze anticipat dacă numesc incorect componentele documentului xml)
1. Obțineți numele elementului rădăcină (în cazul nostru ltm), precum și o listă cu atributele acestuia (versiunea, tipul) și valorile acestora ("1.0", "settings").
2. Obțineți numărul de elemente care sunt copii ai rădăcinii. În acest caz, există 7 dintre ele: templateFiles, dimensiuni, hotspot, hotspot, date, data, data. Obțineți numele elementelor (etichete) (templateFiles, dimensiuni etc.). După ce am primit numărul de elemente și am învățat să le extrag numele, voi rula o buclă de la 0 la count-1 și voi face ceea ce am nevoie.
3. Obțineți cantitatea și lista de atribute ale elementului necesar. De exemplu, pentru elementul hotspot. Răspunsul corect va fi 4 atribute. Pentru primul element hotspot, acestea vor fi numele, stilul, scena, ath. Pentru al doilea - același, doar în loc de atributul ath - atributul rz.
Vă rugăm să rețineți că există 2 elemente hotspot în fișier, cu atribute diferite. Iată cum să lucrezi cu ele (dacă există mai mult de 1 elemente cu același nume)?
Vreau asta: primesc o listă de elemente copil de la rel. la cel rădăcină (vezi punctul 2), rulez o buclă for prin ele și găsesc elemente hotspot al căror parametru de nume este egal cu cel necesar (să spuneți „hs015_2” - cu siguranță va exista un astfel de element). Există vreo modalitate de a rezolva această problemă fără o buclă? Adică, obțineți valoarea atributului scenei pentru elementul hotspot al cărui nume = "hs015_2"?
4. Faceți cele de mai sus în raport cu nodurile și elementele care sunt copii ai copiilor. În exemplul meu, un nod (copilul și părintele lui și.
Dacă am înțeles corect, trebuie să transferați cumva conținutul nodului în variabilă de tip IXMLNode și procedați la fel ca în pașii 1-3. Asa de?
5. Trebuie să învățați cum să modificați parametrii de mai sus (setați singuri).
Asta pare să fie tot deocamdată. În această etapă, structurile sintactice sunt cele mai importante pentru mine.
Cine cunoaște acest subiect, vă rugăm să scrieți și alte construcții sintactice pentru a rezolva întrebările descrise mai sus (cum să obțineți atribute, numărul acestora, numărul de elemente, denumirea lor etc.). Principalul lucru acum este să stăpânesc sintaxa și îmi voi implementa algoritmul mai târziu. Vă mulțumesc mult anticipat tuturor!
P.S. Chiar nu aș vrea să-mi scriu propriul parser XML de la zero doar pentru că cele existente nu au o descriere normală.