Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Loading images from XML 2

Status
Not open for further replies.

lollerskates

Programmer
Aug 4, 2007
8
GB
Hi there

I have an XML file that looks like this:

Code:
<album>
	<slide>
		<image>img01.jpg</image>
		<caption>Image 1</caption>
	</slide>
	<slide>
		<image>img02.jpg</image>
		<caption>Image 2</caption>
	</slide>
</album>

Within delphi I am using TXMLDocument and I have a series of TImage holders for the images to load into. Currently I am loading in the first image using this code:

Code:
myXML := images.DocumentElement.ChildNodes[0];
Image1.picture.loadfromfile(myXML.ChildNodes['image'].NodeValue);

That works fine. What I need to do now though is expand the code so that all of the images are loaded. I've always had a problem with 'for' loops and arrays and I'm pretty sure that's what's needed here.

I need to determine how many child nodes there are and also check if the <image> tag contains an image rather than being blank (because the XML file is going to be extended to include text in addition to the caption - so one of the child nodes may be like this:

Code:
<image></image>
<caption></caption>
<text>some text here</text>

Then I need the image in the first child node to load into the first image holder, the 2nd into the 2nd image holder etc. If the 3rd one doesn't contain an image I just want the 3rd image holder to be blank and continue checking the 4th node for an image right up to the end of the XML file.

*gulp*

Any help with this would be really really appreciated! Thank you!
 
before I respond to this, what Delphi version are you using lollerskates? from D7 Pro there exists a nice XML data binding wizard doing all the work for you...

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Really!? I have Delphi 7 Enterprise edition.

Thank you for your response!
 
okay, check if you have it. openup delphi and goto
File / New / Other / XML Data Binding

do you have this?

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
alright :)

you're gonna like this tool, it will save you a lot of time.

what I always do is make a complete as possible template xml file and feed it to the wizard

so in your case :

Code:
<?xml version="1.0" encoding="utf-8"?>
<album>
    <slide>
        <image></image>
        <caption></caption>
        <Description></Description>
    </slide>
    <slide>
        <image></image>
        <caption></caption>
        <Description></Description>
    </slide>
</album>

as you can see I added a description tag.

it is very important that you repeat sections that are repetetive (I mean the slide tag in this case), the tool will see this and make the apropriate code. save the above code into an xml file and feed it to the wizard. you'll get something like this :

Code:
{**********************************************************}
{                                                          }
{                     XML Data Binding                     }
{                                                          }
{         Generated on: 5/08/2007 21:47:39                 }
{       Generated from: C:\Delphi2006\Projects\album.xml   }
{   Settings stored in: C:\Delphi2006\Projects\album.xdb   }
{                                                          }
{**********************************************************}

unit album;

interface

uses xmldom, XMLDoc, XMLIntf;

type

{ Forward Decls }

  IXMLAlbumType = interface;
  IXMLSlideType = interface;

{ IXMLAlbumType }

  IXMLAlbumType = interface(IXMLNodeCollection)
    ['{B09B35ED-6AB6-4FB1-9B65-6297EEF38999}']
    { Property Accessors }
    function Get_Slide(Index: Integer): IXMLSlideType;
    { Methods & Properties }
    function Add: IXMLSlideType;
    function Insert(const Index: Integer): IXMLSlideType;
    property Slide[Index: Integer]: IXMLSlideType read Get_Slide; default;
  end;

{ IXMLSlideType }

  IXMLSlideType = interface(IXMLNode)
    ['{51001F48-D5BA-4C1A-8B03-6285A7874627}']
    { Property Accessors }
    function Get_Image: WideString;
    function Get_Caption: WideString;
    function Get_Description: WideString;
    procedure Set_Image(Value: WideString);
    procedure Set_Caption(Value: WideString);
    procedure Set_Description(Value: WideString);
    { Methods & Properties }
    property Image: WideString read Get_Image write Set_Image;
    property Caption: WideString read Get_Caption write Set_Caption;
    property Description: WideString read Get_Description write Set_Description;
  end;

{ Forward Decls }

  TXMLAlbumType = class;
  TXMLSlideType = class;

{ TXMLAlbumType }

  TXMLAlbumType = class(TXMLNodeCollection, IXMLAlbumType)
  protected
    { IXMLAlbumType }
    function Get_Slide(Index: Integer): IXMLSlideType;
    function Add: IXMLSlideType;
    function Insert(const Index: Integer): IXMLSlideType;
  public
    procedure AfterConstruction; override;
  end;

{ TXMLSlideType }

  TXMLSlideType = class(TXMLNode, IXMLSlideType)
  protected
    { IXMLSlideType }
    function Get_Image: WideString;
    function Get_Caption: WideString;
    function Get_Description: WideString;
    procedure Set_Image(Value: WideString);
    procedure Set_Caption(Value: WideString);
    procedure Set_Description(Value: WideString);
  end;

{ Global Functions }

function Getalbum(Doc: IXMLDocument): IXMLAlbumType;
function Loadalbum(const FileName: WideString): IXMLAlbumType;
function Newalbum: IXMLAlbumType;

const
  TargetNamespace = '';

implementation

{ Global Functions }

function Getalbum(Doc: IXMLDocument): IXMLAlbumType;
begin
  Result := Doc.GetDocBinding('album', TXMLAlbumType, TargetNamespace) as IXMLAlbumType;
end;

function Loadalbum(const FileName: WideString): IXMLAlbumType;
begin
  Result := LoadXMLDocument(FileName).GetDocBinding('album', TXMLAlbumType, TargetNamespace) as IXMLAlbumType;
end;

function Newalbum: IXMLAlbumType;
begin
  Result := NewXMLDocument.GetDocBinding('album', TXMLAlbumType, TargetNamespace) as IXMLAlbumType;
end;

{ TXMLAlbumType }

procedure TXMLAlbumType.AfterConstruction;
begin
  RegisterChildNode('slide', TXMLSlideType);
  ItemTag := 'slide';
  ItemInterface := IXMLSlideType;
  inherited;
end;

function TXMLAlbumType.Get_Slide(Index: Integer): IXMLSlideType;
begin
  Result := List[Index] as IXMLSlideType;
end;

function TXMLAlbumType.Add: IXMLSlideType;
begin
  Result := AddItem(-1) as IXMLSlideType;
end;

function TXMLAlbumType.Insert(const Index: Integer): IXMLSlideType;
begin
  Result := AddItem(Index) as IXMLSlideType;
end;

{ TXMLSlideType }

function TXMLSlideType.Get_Image: WideString;
begin
  Result := ChildNodes['image'].Text;
end;

procedure TXMLSlideType.Set_Image(Value: WideString);
begin
  ChildNodes['image'].NodeValue := Value;
end;

function TXMLSlideType.Get_Caption: WideString;
begin
  Result := ChildNodes['caption'].Text;
end;

procedure TXMLSlideType.Set_Caption(Value: WideString);
begin
  ChildNodes['caption'].NodeValue := Value;
end;

function TXMLSlideType.Get_Description: WideString;
begin
  Result := ChildNodes['Description'].Text;
end;

procedure TXMLSlideType.Set_Description(Value: WideString);
begin
  ChildNodes['Description'].NodeValue := Value;
end;

end.

you see it generates a lot of code from your small XML file.
now why amll the fuss?

well you can approach your XML structure like a class.
in this case you have a main class called TXMLAlbumType.
remember to refer to the classes via their interface so in this case it will be IXMLAlbumType.

a small example how to read all slides

Code:
...
var MyAlbum : IXMLAlbumType;

procedure ReadSlides(Album : IXMLAlbumType);

var Index : Integer;
    Slide : IXMLSlideType;

begin
 Index := Album.Count; // this will return the number of slide nodes under album, in fact this is a property from IXMLNode
 while Index > 0 do
 begin
  Dec(Index);
  Slide := Album.Slide[Index];
  // access the nodes like properties
  DescriptiveLabel.Caption := Slide.Description;
  // and so on...
 end;
end;

// main

begin
 MyAlbum := Loadalbum('Album.xml');
 if not Assigned(MyAlbum) then showmessage('there is something wrong with your XML file!!!');
 ReadSlides(MyAlbum); 
end.

As you can see this is one powerful tool.
forgot a property? no problem, adjust the template, rerun wizard and reuse the unit.

Cheers,
Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Wow, thank you so much! I'm going to give this a try tonight. Wooohooo! Looks great! :D
Thanks again!
 
np man and good luck!

[thumbsup]
Daddy

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
I'm getting an "undeclared identifier DescriptiveLabel"

Do I need something in my uses section?

Is the code you posted meant to go in the XML code bit or in the code for the form?
 
well i got that bit figured out and its reading the xml but only the first slide - i'm not totally understanding how it is supposed to read through them all. the count is working though, that's all i know :D
 
maybe it is more clear to you if you do this :

Code:
procedure ReadSlides(Album : IXMLAlbumType);

var Index : Integer;
    Slide : IXMLSlideType;

begin
 for Index := 0 to  Album.Count-1 do
 begin
  Dec(Index);
  Slide := Album.Slide[Index];
  // access the nodes like properties
  showmessage(Slide.Description);
  // and so on...
 end;
end;

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Hi there, sorry about this!

The line "dec(Index)" is returning an error saying "assignment to FOR-Loop variable Index"

When I take it out, the showmessage shows the first description then the next etc, like it should do.

So, my problem now (apart from that error) is how to display the results on the form. when i have a label called "descriptivelabel" on the form it displays the info from the last 'slide' in the xml.

if i have 6 slides, and 6 descriptivelabels - what do i call the labels on the form?

Sorry about this - and thank you !!!!
 
sorry,

the dec(index) line must go offcourse (it was used for the while..do loop).

from what I understand you're trying to show a certain (variable) amount of slides.

there are a number of ways to do this.

the best approach is to create a new component.

a TPanel that encapsulates a TImage and a TLabel.



-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
hi, yeah i do need to show a variable number of slides (depending on what is contained in the XML).

but my first problem is that i want label1 to contain the description in the first node, label2 to contain the description in the 2nd node etc..

im not sure what way to set the labels up on the form to capture this info.

thanks again!
 
DADDY - I wish I could give you 10 stars for this! Several years ago, I wrote an XML parser for a POS project that had huge xml files. I did it all by hand not knowing this great tool was built into D7.

I do have a question. Is there an inverse to this? For example, if I have a folder with subfolders (albums) of jpg's (slides), what is the simplest way to generate an input XML file?


Roo
Delphi Rules!
 
mmm,

that's a nice question roo.

in your case I'd use the same unit and create the xml from the NewAlbum function. then offourse you need to scan the directories, add slides to the XML interface and finally create the XML file with

MyAlbum.OwnerDocument.SaveToFile('album.xml');


/Daddy


-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
no, not .NET.

actually TXMLDocument is available from D6

-----------------------------------------------------
What You See Is What You Get
Never underestimate tha powah of tha google!
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top