XML Tutorial/hu
│
Deutsch (de) │
English (en) │
español (es) │
français (fr) │
magyar (hu) │
Bahasa Indonesia (id) │
italiano (it) │
日本語 (ja) │
한국어 (ko) │
português (pt) │
русский (ru) │
中文(中国大陆) (zh_CN) │
XML Tananyag
Bevezetés
A Kiterjeszthető jelölőnyelv (Extensible Markup Language) egy, a W3C által ajánlott nyelv, amely azért jött létre, hogy információcserét tegyen lehetővé különböző rendszerek között. Ez egy szövegalapú módszere az információ tárolásnak. A modern adatcsere nyelvek, mint az XHTML, úgy, mint a legtöbb WebServices technológia, XML alapú.
Jelenleg, van egy unit-készlet, amely támogatja az XML használatát Free Pascal-lal. Ezek a unit-ok a következők: "XMLRead", "XMLWrite" és a "DOM". Ezek részei a szabad komponenstárnak (FCL). Az FCL már szerepel a Lazarus unit keresési útvonalai között, tehát neked már csak annyi a dolgod, hogy ezeket a unit-okat hozzáadd a uses szekciódhoz az XML támogatás használatához. Az FCL nincs dokumentálva jelenleg (2005. októbere), tehát ennek a segédletnek az a célja, hogy bemutassa az XML használatát ezekkel a unit-okkal.
Az XML DOM (Dokumentum Objektum Modell), szabványosított objektumok gyűjteménye, amely hasonló felületet nyújt az XML használatához különféle nyelveken és rendszereken. A szabvány csak a metódusokat, tulajdonságokat és az objektum egyéb elemeit határozza meg, szabadon hagyva az implementáció lehetőségét a különböző nyelveknek. Az FCL jelenleg a teljes XML DOM 1.0-t támogatja.
Példák
Lejjebb találsz egy listát az XML adatok kezelésével kapcsolatos példákról, fokozatosan növekvő bonyolultsággal.
Szövegelem olvasása
Delphi programozóknak: Vedd figyelembe, hogy amikor egy TXMLDocument-tel dolgozunk, az elemen belüli szöveg, egy különálló szövegelemként van kezelve. Ennek eredményeként: egy elem szövegét úgy tudod elérni, ha különálló elemként tekinted. Másik megoldás: a TextContent tulajdonság használható, hogy egy adott elem összes szövegtartalmát, összefűzve megszerezd.
A ReadXMLFile függvény mindig létrehoz egy új TXMLDocument-et, tehát neked nem kell előzőleg kézzel létrehoznod. Ellenben, ne felejtsd el felszabadítani a dokumentumot a Free meghívásával, amikor kész vagy.
Például, vegyük a következő XML-t:
<?xml version="1.0"?>
<request>
<request_type>PUT_FILE</request_type>
<username>123</username>
<password>abc</password>
</request>
A következő példakód bemutatja mind a helyes, mind a helytelen módját egy szövegelem értékének megszerzéséhez:
var
PassNode: TDOMNode;
Doc: TXMLDocument;
begin
// XML fájl beolvasása a lemezről
ReadXMLFile(Doc, 'c:\xmlfiles\test.xml');
// A "password" elem beolvasása
PassNode := Doc.DocumentElement.FindNode('password');
// A kiválasztott elem értékének kiíratása
WriteLn(PassNode.NodeValue); // üres lesz
// Az elem szövege valójában egy különálló gyerek elem
WriteLn(PassNode.FirstChild.NodeValue); // helyesen kiírja az "abc"-t
// másképpen:
WriteLn(PassNode.TextContent);
// végül, felszabadítjuk a dokumentumot:
Doc.Free;
end;
Az elemek nevének kiíratása
Egy gyors megjegyzés a DOM fában való navigáláshoz: Amikor az elemeket sorrendben kell elérned, a legjobb a FirstChild és a NextSibling tulajdonságok használata (előre való lépkedéshez), vagy a LastChild és a PreviousSibling (hátrafelé lépkedéshez). Véletlenszerű eléréshez használhatók a ChildNodes vagy a GetElementsByTagName metódusok, de ezek egy TDOMNodeList objektumot fognak létrehozni, amit szintén fel kell szabadítani. Ez eltér más DOM implementációktól, mint pl. az MSXML, mert az FCL implementáció objektum, nem pedig interfész alapú.
A következő példa bemutatja, hogy hogyan írassuk ki az elemek nevét egy TMemo-ba.
Ez a 'C:\Programok\test.xml' fájl tartalma:
<?xml version="1.0"?>
<images directory="mydir">
<imageNode URL="graphic.jpg" title="">
<Peca DestinoX="0" DestinoY="0">Pecacastelo.jpg1.swf</Peca>
<Peca DestinoX="0" DestinoY="86">Pecacastelo.jpg2.swf</Peca>
</imageNode>
</images>
És itt a Pascal kód a feladat végrehajtásához:
var
Document: TXMLDocument;
Child: TDOMNode;
j: Integer;
begin
ReadXMLFile(Document, 'C:\Programok\test.xml');
Memo.Lines.Clear;
// FirstChild és NextSibling használatával:
Child := Document.DocumentElement.FirstChild;
while Assigned(Child) do
begin
Memo.Lines.Add(Child.NodeName + ' ' + Child.Attributes.Item[0].NodeValue);
// ChildNodes metódus használatával:
with Child.ChildNodes do
try
for j := 0 to (Count - 1) do
Memo.Lines.Add(Item[j].NodeName + ' ' + Item[j].FirstChild.NodeValue);
finally
Free;
end;
Child := Child.NextSibling;
end;
Document.Free;
end;
Ez lesz a kimenet:
imageNode graphic.jpg Peca Pecacastelo.jpg1.swf Peca Pecacastelo.jpg1.swf
Fastruktúra feltöltése XML-lel
Egy elterjedt módja az XML fájlok használatának, az, hogy a tartalmukat egy fastruktúrában használjuk fel. A TTreeView komponens a "Common Controls" fülön található a Lazarus-ban.
A lenti függvény egy előzőleg betöltött vagy a kódban generált XML dokumentum alapján feltölt egy fastruktúrát a tartalmával. Minden egyes elem megnevezése az első attribútumának tartalma lesz.
procedure TForm1.XML2Tree(tree: TTreeView; XMLDoc: TXMLDocument);
var
iNode: TDOMNode;
procedure ProcessNode(Node: TDOMNode; TreeNode: TTreeNode);
var
cNode: TDOMNode;
s: string;
begin
if Node = nil then Exit; // Kilépés, ha egy ág végére értünk
// Elem hozzáadása a fához
if Node.HasAttributes and (Node.Attributes.Length>0) then
s:=Node.Attributes[0].NodeValue
else
s:='';
TreeNode := tree.Items.AddChild(TreeNode, s);
// Ugrás az első gyerek elemhez
cNode := Node.FirstChild;
// Gyerek elemek feldolgozása
while cNode <> nil do
begin
ProcessNode(cNode, TreeNode);
cNode := cNode.NextSibling;
end;
end;
begin
iNode := XMLDoc.DocumentElement.FirstChild;
while iNode <> nil do
begin
ProcessNode(iNode, nil); // Rekurzívan
iNode := iNode.NextSibling;
end;
end;
XML dokumentum módosítása
Az első dolog, amit meg kell jegyezni, az hogy a TDOMDocument a "handle" a DOM-hoz. Úgy jöhet létre ennek az osztálynak példánya, hogy saját kezűleg létrehozod, vagy egy XML dokumentumot betöltesz.
Másfelől, az elemek nem hozhatók létreh úgy, mint egy normál objektum. A TDOMDocument metódusait KELL használod, hogy létrehozd őket, és később más metódusokat, hogy a megfelelő helyre tehesd őket a szerkezetben. Ez azért van, mert az elemeket egy meghatározott dokumentumnak kell birtokolnia a DOM-ban.
Lejjebb található a TDOMDocument néhány általános metódusa:
function CreateElement(const tagName: DOMString): TDOMElement; virtual;
function CreateTextNode(const data: DOMString): TDOMText;
function CreateCDATASection(const data: DOMString): TDOMCDATASection;
virtual;
function CreateAttribute(const name: DOMString): TDOMAttr; virtual;
És itt egy példa, ami megkeresi a TTreeView-ben kijelölt elemet és elhelyez egy gyerek elemet abba az XML dokumentumba, amelyet reprezentál. A fastruktúrát előtte fel kell tölteni egy XML fájl tartalmával a XML2Tree function használatával.
procedure TForm1.actAddChildNode(Sender: TObject);
var
position: Integer;
NovoNo: TDomNode;
begin
{*******************************************************************
* Megkeresi a kijelölt elemet
*******************************************************************}
if TreeView1.Selected = nil then Exit;
if TreeView1.Selected.Level = 0 then
begin
position := TreeView1.Selected.Index;
NovoNo := XMLDoc.CreateElement('item');
TDOMElement(NovoNo).SetAttribute('nome', 'Item');
TDOMElement(NovoNo).SetAttribute('arquivo', 'Arquivo');
with XMLDoc.DocumentElement.ChildNodes do
begin
Item[position].AppendChild(NovoNo);
Free;
end;
{*******************************************************************
* A fastruktúra frissítése
*******************************************************************}
TreeView1.Items.Clear;
XML2Tree(TreeView1, XMLDoc);
end
else if TreeView1.Selected.Level >= 1 then
begin
{*******************************************************************
* Ez a függvény a fának csak az első szintjén működik,
* de egyszerűen módosítható úgy, hogy bármelyiken működjön
*******************************************************************}
end;
end;
TXMLDocument létrehozása string-ből
Adott egy XML fájl a MyXmlString-ben. A következő kód létrehozza a DOM-ját:
Var
S : TStringStream;
XML : TXMLDocument;
begin
S:= TStringStream.Create(MyXMLString);
Try
S.Position:=0;
XML:=Nil;
ReadXMLFile(XML,S); // Teljes XML dokumentum
// Másképpen:
ReadXMLFragment(AParentNode,S); // Csak az XML töredék beolvasása.
Finally
S.Free;
end;
end;
Dokumentum érvényesítése
2007. márciusa óta, a DTD érvényesítési képesség lett hozzáadva az FCL XML feldogozóhoz. Az érvényesítés ellenőrzi a dokumentum logikai felépítését az előre meghatározott szabályoknak alapján (ez a Document Type Definition /DTD/).
Itt egy példa DTD-vel ellátott XML dokumentumra:
<?xml version='1.0'?>
<!DOCTYPE root [
<!ELEMENT root (child)+ >
<!ELEMENT child (#PCDATA)>
]>
<root>
<child>Ez az első gyerek.</child>
<child>Ez a második gyerek.</child>
</root>
Ez a DTD meghatározza, hogy a 'root' elemnek egy vagy több 'child' elemének kell lennie, és hogy a 'child' elemek csak karakteres adatot tartalmazhatnak. Ha a feldolgozó eltérést érzékel ehhez képest, jelenteni fogja.
Egy ilyen dokumentum beolvasása jóval bonyolultabb. Vegyük azt, hogy XML adatunk van egy TStream objektumban:
procedure TMyObject.DOMFromStream(AStream: TStream);
var
Parser: TDOMParser;
Src: TXMLInputSource;
TheDoc: TXMLDocument;
begin
// feldolgozó objektum létrehozása
Parser := TDOMParser.Create;
// és a bemeneti forrás
Src := TXMLInputSource.Create(AStream);
// kérünk érvényesítést
Parser.Options.Validate := True;
// hibakezelő hozzárendelése, ami figyeli a jelentéseket
Parser.OnError := @ErrorHandler;
// most jöhet a feldolgozás
Parser.Parse(Src, TheDoc);
// ...és most takarítás
Src.Free;
Parser.Free;
end;
procedure TMyObject.ErrorHandler(E: EXMLReadError);
begin
if E.Severity = esError then // csak az érvényesítési hibák érdekelnek
writeln(E.Message);
end;
XML fájl létrehozása
Lejjebb található egy teljes kód XML fájlba íráshoz. (Ez a DeveLazarus blog-ból lett másolva) Ne felejtsd el a DOM és az XMLWrite unit-okat a uses szekcióban!
unit Unit1;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls,
DOM, XMLWrite;
type
{ TForm1 }
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;
var
Form1: TForm1;
implementation
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
xdoc: TXMLDocument; // dokumentum változó
RootNode, parentNode, nofilho: TDOMNode; // elemek változói
begin
// dokumentum létrehozása
xdoc := TXMLDocument.create;
// gyökér elem létrehozása
RootNode := xdoc.CreateElement('register');
Xdoc.Appendchild(RootNode); // gyökér elem mentése
// szülő elem létrehozása
RootNode:= xdoc.DocumentElement;
parentNode := xdoc.CreateElement('usuario');
TDOMElement(parentNode).SetAttribute('id', '001'); // attribútumok létrehozása a szülő elemhez
RootNode.Appendchild(parentNode); // szülő elem mentése
// gyerek elem létrehozása
parentNode := xdoc.CreateElement('nome');
//TDOMElement(parentNode).SetAttribute('sexo', 'M'); // attribútumok létrehozása
nofilho := xdoc.CreateTextNode('Fernando'); // értékadás az elemhez
parentNode.Appendchild(nofilho); // elem mentése
RootNode.ChildNodes.Item[0].AppendChild(parentNode); // gyerek elem hozzáadása a hozzátartozó szülőhöz
// gyerek elem létrehozása
parentNode := xdoc.CreateElement('idade');
//TDOMElement(parentNode).SetAttribute('ano', '1976'); // attribútumok létrehozása
nofilho := xdoc.CreateTextNode('32'); // értékadás az elemhez
parentNode.Appendchild(nofilho); // elem mentése
RootNode.ChildNodes.Item[0].AppendChild(parentNode); // gyerek elem hozzáadása a hozzátartozó szülőhöz
writeXMLFile(xDoc,'teste.xml'); // kiírás XML-be
Xdoc.free; // memória felszabadítása
end;
initialization
{$I unit1.lrs}
end.
Az eredmény a következő XML fájl:
<?xml version="1.0"?>
<register>
<usuario id="001">
<nome>Fernando</nome>
<idade>32</idade>
</usuario>
</register>
--Fernandosinesio 22:28, 24 April 2008 (CEST)fernandosinesio@gmail.com
Kódolás
Az 12582-es SVN revíziótól kezdődően, az XML olvasó alkalmas bármilyen kódolású adat feldolgozásához, külső dekódolók használatával. Lásd: XML_Decoders tovább részletekért.
Az XML szabvány alapján, az 'encoding' attribútum az XML első sorában opcionális, abban az esetben, ha a kódolás UTF-8 vagy UTF-16 (ami a BOM jelenlétéből határozható meg). A 0.9.26-os Lazarus verziótól, a TXMLDocument-nek van 'encoding' tulajdonsága, de ez tiltva van. A WriteXMLFile mindig UTF-8-at használ és nem hoz létre encoding attribútumot az XML fájl első sorában.
Külső hivatkozások
- W3Schools Xml tananyag
- Thomas Zastrow cikke FPC és XML