FAQ DelphiConsultez toutes les FAQ
Nombre d'auteurs : 124, nombre de questions : 934, dernière mise à jour : 23 octobre 2024 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).
Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.
L'équipe Delphi de Developpez.com.
- Comment créer/ouvrir un fichier XML ?
- Comment créer la structure d'un fichier XML ?
- Comment charger un TTreeView avec le contenu d'un document XML ?
- Comment savoir si un document XML est syntaxiquement correct ?
- Comment lire la valeur d'un noeud sans violation d'accès ?
- Comment valider un XML avec un XSD ?
- Qu'est-ce que Xml Mapper ?
- Comment récupérer un noeud par son nom ?
- Comment transformer dynamiquement un XML grâce à un XSL ?
Le composant TXMLDocument, situé dans la page de composants Internet, nous permet de manipuler les fichiers xml à partir de Delphi.
On peut procéder de deux façons :
> Utiliser la propriété FileName pour spécifier le nom d'un fichier xml existant.
> Utiliser la propriété XML pour entrer du xml sous forme de chaîne.
Dans tous les cas, il faut spécifier l'implémentation DOM en attribuant une valeur à la propriété DOMVendor; sans cela le fichier xmlne pourra pas être traité.
Une fois ceci fait, on met la propriété Active du TXMLDocument à true pour commencer à traiter le contenu de la propriété XML (qui dans le cas où FileName est renseigné contient tout le contenu de ce dernier).
Il faut noter par ailleurs que FileName doit être une fichier existant. Pour créer un fichier XML, il suffit alors de renseigner la propriété XML, puis en fin de traitement d'utiliser la méthode SaveToFile pour créer le fichier xml.
Les méthodes du composant TXMLDocument nous permettent de créer la structure d'un fichier XML. Ce dernier ayant une structure d'arbre, il faut noter que la racine correspond à la valeur de la propriété DocumentElement.
Un nœud peut être (à part la racine) :
> interne ou
> une feuille.
Toutes les méthodes sont celles de la collection ChildNodes qui représente l'ensemble des nœuds enfants d'un nœud donné.
Les méthodes qui permettent de créer des nœuds sont CreateNode et AddChild.
On utilise CreateElement pour créer une feuille. Celle-ci n'a pas un parent associé et il faudra manuellement l'ajouter à la liste des enfants d'un nœud existant.
CreateNode permet de créer un nœud générique qui pourra ensuite être intégré dans une hiérarchie existante (en tant que fils d'un nœud par exemple).
Le code suivant permet de créer un nœud et de l'ajouter en tant qu'enfant d'un autre nœud :
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var UnNoeud : IXMLNode; Feuille : IXMLNode; begin XMLDoc.Active := True; //On crée un noeud UnNoeud := XMLDoc.CreateNode('QR', ntElement); //on crée une feuille. La balise correspondante à celle-ci est donnée Feuille := XMLDoc.CreateElement('Donnee', ''); //On donne une valeur à la feuille Feuille.NodeValue := 'Rien'; //On ajoute la feuille dans le noeud UnNoeud.ChildNodes.Add(Feuille); //On ajoute le noeud dans la hiérarchie de notre document XMLDoc.DocumentElement.ChildNodes.Add(UnNoeud); //Pour être sûr que le code a été correctement exécuté ShowMessage(XMLDoc.XML.Text); end; |
Un autre code qui réalise la même opération mais en utilisant AddChild cette fois :
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 | var Feuille : IXMLNode; begin XMLDoc.Active := True; Feuille := XMLDoc.CreateElement('Donnee', ''); Feuille.NodeValue := 'Rien'; //Le nœud est inséré dans une queue de collection XMLDoc.DocumentElement.AddChild('Nouveau'); XMLDoc.DocumentElement.ChildNodes.Last.ChildNodes.Add(Feuille); end; |
Il faut préciser par ailleurs que remplacer la racine par un nouveau nœud, détruit la structure du XML !
La suppression d'un nœud se fait en utilisant la méthode Delete de la collection ChildNodes.
La procédure ci-dessous nous permet de remplir un TTreeView avec le contenu d'un document XML (TvXML désigne un TTreeView préalablement déposé sur la fiche).
Code Delphi : | Sélectionner tout |
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 26 27 28 29 30 31 32 33 | procedure TFrmTreeviewXML.LoadXMLInTree(XMLNode: IXMLNode; TreeNode: TTreeNode); var I: Integer; Noeud : TTreeNode; TexteDuNoeud: string; AttributNoeud: IXMLNode; begin //Les nœuds internes sont traités récursivement if XMLNode.NodeType <> ntElement then Exit; //On ajoute le nœud courant TexteDuNoeud := XmlNode.NodeName; //S'il s'agit d'une feuille if XMLNode.IsTextElement then TexteDuNoeud := TexteDuNoeud + ' = ' + XMLNode.NodeValue; Noeud := TvXML.Items.AddChild(TreeNode, TexteDuNoeud); //S'il y a des attributs on les ajoute... for I := 0 to XMLNode.AttributeNodes.Count - 1 do begin AttributNoeud := XMLNode.AttributeNodes.Nodes[I]; TvXML.Items.AddChild(Noeud,'[' + AttributNoeud.NodeName + ' = "' + AttributNoeud.Text + '"]'); end; //si le nœud courant a des nœuds enfants, on les ajoute if XMLNode.HasChildNodes then for I := 0 to XMLNode.ChildNodes.Count - 1 do LoadXMLInTree(XMLNode.ChildNodes.Nodes [I], Noeud); end; |
Pour l'appel de la procédure, on peut le faire dans l'événement OnClick d'un bouton :
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | procedure TFrmTreeviewXML.BtnLoadClick(Sender: TObject); begin //On efface le contenu du TreeView TvXML.Items.Clear; XMLDoc.Active := True; //Pour éviter le scintillement avec les gros fichiers... TvXML.Items.BeginUpdate; LoadXMLInTree(XMLDoc.DocumentElement, nil); TvXML.Items.EndUpdate; end; |
On distingue les documents valides des documents bien formés. Un document valide est celui qui respecte son DTD tandis qu'un document bien formé est celui qui respecte la syntaxe du XML. Lorsqu'on essaie d'ouvrir un document mal formé avec un navigateur, il nous indique la position et la raison de l'erreur.
La fonction que nous présentons ci-dessous prend un nom de fichier xml en paramètre et indique dans le cas d'une erreur la ligne, la colonne et la raison de l'erreur :
Code Delphi : | Sélectionner tout |
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | (*Supprimer les commentaires pour afficher les messages appropriés*) function IsXMLWellFormed(XMLFileName : String) : Boolean; var ParseError: IDOMParseError;//Interface permettant de recupérer les erreurs dans le xml FileContent : TStringList; //Pour stocker le contenu du fichier begin Result := False; //Une simple vérification d'extension if UpperCase(ExtractFileExt(XMLFileName)) <> UpperCase('.xml') then begin MessageDlg('Extension de fichier incorrecte!', mtError, [mbOK], 0); Exit; end; //Ouverture du document : On doit l'ouvrir pour que le parser puisse interpréter son contenu XMLDoc.Active := True; FileContent := TStringList.Create; (* TXMLDocument implémente l'interface IXMLDocumentAccess qui nous permet d'accéder aux propriétés protégées de TXMLDocument (une en particulier, DOMPersist est utilisée dans le code pour charger le contenu du fichier xml) *) try try FileContent.LoadFromFile(XMLFileName); (XMLDoc as IXMLDocumentAccess).DOMPersist.LoadXML(FileContent.Text); finally FileContent.Free; end; except on E : Exception do begin //ShowMessage(E.Message); Exit; end; end; ParseError := (XMLDoc.DOMDocument as IDOMParseError); if ParseError.ErrorCode <> 0 then with ParseError do begin //MessageDlg('Erreur à la ligne ' + IntToStr(Line) + 'Position ' + IntToStr(linePos) + //#13#10 + Reason, mtError, [mbOK], 0); Exit; end; Result := True; //MessageDlg('Document bien formé!', mtInformation, [mbOK], 0); end; |
En protégeant correctement le code. Un simple Try Except ne suffit pas, il faut également vérifier que le nœud sur lequel on travaille existe bien. Pour ce faire, on utilise la fonction Assigned.
Il existe aussi le problème des valeurs null. Si la valeur est null, on ne pourra pas la transformer en string. Il faut donc tester la valeur et le cas échéant, traiter la valeur null. C'est ce que fait VarIsNull.
La fonction suivante permet de récupérer la valeur String d'un nœud. Vous devez fournir en paramètre la référence du nœud sur lequel vous travaillez.
Code Delphi : | Sélectionner tout |
Noeud := XMLDocument1.ChildNodes['RACINE'].ChildNodes['MonNoeud'];
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | function XMLNodeValue(Noeud : IXMLNode; DefaultValue : string) : string; begin if assigned(noeud) then try if not VarIsNull(noeud.NodeValue) then Result := noeud.NodeValue else Result := DefaultValue; except Result := DefaultValue; end else result := DefaultValue; end; |
Une solution consiste à utiliser l'ActiveX MSXML 4.0.
Code Delphi : | Sélectionner tout |
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | unit UXMLvalidation; interface uses Classes, SysUtils, msxmldom, MSXML2_TLB, { Il faut importer l'activeX MSXML DOM2 4.0 pour obtenir l'unité MSXML2_TLB.pas } xmldom, XMLDoc, XMLIntf; { Pour une utilisation de TXMLDocument } type EXMLDOMValidationError = class(Exception) private FSrcText: DOMString; FURL: DOMString; FReason: DOMString; FErrorCode: Integer; FLine: Integer; FLinePos: Integer; FFilePos: Integer; public constructor Create(const ValidationError: IXMLDOMParseError); property ErrorCode: Integer read FErrorCode; property URL: DOMString read FURL; property Reason: DOMString read FReason; property SrcText: DOMString read FSrcText; property Line: Integer read FLine; property LinePos: Integer read FLinePos; property FilePos: Integer read FFilePos; end; procedure ValidateXMLFileName(XMLFilename, XSDFilename: TFileName; NameSpaceSchema: string); procedure ValidateXMLText(XMLText: string; XSDFilename: TFileName; NameSpaceSchema: string); procedure ValidateXMLDoc(XMLDoc, XSDDoc: IXMLDOMDocument2; NameSpaceSchema: string); // Génère une exception EXMLDOMValidationError si errorcode<>0 procedure CheckValidationError(ValidationError: IXMLDOMParseError); // Permet de retrouver l'interface COM de MSXML à partir d'un IXMLDocument (Borland) // Attention: le IXMLDocument doit avoir dans ce cas MSXML comme Vendor ! function GetXMLDOMDocument2(XMLDoc: IXMLDocument): IXMLDOMDocument2; resourcestring RS_EXMLDOM_FILE_VALIDATION_ERROR = 'Document XML non conforme au schéma.'#13#10#13#10+ 'Raison:'#13#10'%s'#13#10+ 'Ligne: %d'#13#10+ 'Position: %d'#13#10+ 'Position dans le fichier: %d'#13#10+ 'URL: %s'#13#10+ 'XML: '#13#10'%s'; RS_EXMLDOM_NOFILE_VALIDATION_ERROR = 'Document XML non conforme au schéma.'#13#10#13#10+ 'Raison:'#13#10'%s'#13#10; implementation { EXMLDOMValidationError } constructor EXMLDOMValidationError.Create( const ValidationError: IXMLDOMParseError); begin FSrcText := ValidationError.srcText; FURL := ValidationError.url; FReason := ValidationError.reason; FErrorCode := ValidationError.errorCode; FLine := ValidationError.line; FLinePos := ValidationError.linepos; FFilePos := ValidationError.filepos; if FLine>0 then inherited CreateResFmt(@RS_EXMLDOM_FILE_VALIDATION_ERROR, [FReason, FLine, FLinePos, FFilePos, FURL, FSrcText]) else inherited CreateResFmt(@RS_EXMLDOM_FILE_VALIDATION_ERROR, [FReason]); end; function GetXMLDOMDocument2(XMLDoc: IXMLDocument): IXMLDOMDocument2; begin XMLDoc.Active := True; Result := ((XMLDoc.DOMDocument as IXMLDOMNodeRef).GetXMLDOMNode as IXMLDOMDocument2); end; procedure CheckValidationError(ValidationError: IXMLDOMParseError); begin if ValidationError.errorCode<>0 then raise EXMLDOMValidationError.Create(ValidationError); end; procedure ValidateXMLDoc(XMLDoc, XSDDoc: IXMLDOMDocument2; NameSpaceSchema: string); var vSchemaCollection: IXMLDOMSchemaCollection2; begin vSchemaCollection := CoXMLSchemaCache40.Create; vSchemaCollection.add(NameSpaceSchema, XSDDoc); XMLDoc.schemas := vSchemaCollection; CheckValidationError(XMLDoc.validate); end; procedure ValidateXMLFilename(XMLFilename, XSDFilename: TFileName; NameSpaceSchema: string); var vXML, vSchema: IXMLDOMDocument2; vSchemaCollection: IXMLDOMSchemaCollection2; begin vSchema := CoDOMDocument40.Create; vSchema.async := False; vSchema.load(XSDFilename); vSchemaCollection := CoXMLSchemaCache40.Create; vSchemaCollection.add(NameSpaceSchema, vSchema); vXML := CoDOMDocument40.Create; vXML.async := False; vXML.validateOnParse := True; vXML.schemas := vSchemaCollection; vXML.load(XMLFilename); CheckValidationError(vXML.parseError); end; procedure ValidateXMLText(XMLText: string; XSDFilename: TFileName; NameSpaceSchema: string); var vXML, vSchema: IXMLDOMDocument2; vSchemaCollection: IXMLDOMSchemaCollection2; begin vSchema := CoDOMDocument40.Create; vSchema.async := False; vSchema.load(XSDFilename); vSchemaCollection := CoXMLSchemaCache40.Create; vSchemaCollection.add(NameSpaceSchema, vSchema); vXML := CoDOMDocument40.Create; vXML.async := False; vXML.validateOnParse := True; vXML.schemas := vSchemaCollection; vXML.loadXML(XMLText); CheckValidationError(vXML.parseError); end; end. |
Xml mapper est un outil de conversion. Il permet de transformer un document Xml standard en un paquet de données utilisable dans Delphi (aussi un fichier xml).
Ce nouveau document xml-data packet peut servir de support de base de données, car il contient la structure de la base.
Le Xml original :
Code xml : | Sélectionner tout |
1 2 3 4 5 | <Root> <AAA>Hello World</AAA> <BBB name="Big"/> <CCC name="test">Xml Mappeur</CCC> </Root> |
Code xml : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | <DATAPACKET Version="2.0"> <METADATA> <FIELDS> <FIELD attrname="AAA" fieldtype="string" WIDTH="11"/> <FIELD attrname="BBB_name" fieldtype="string" WIDTH="3"/> <FIELD attrname="CCC" fieldtype="string" WIDTH="11"/> <FIELD attrname="CCC_name" fieldtype="string" WIDTH="3"/> </FIELDS> <PARAMS/> </METADATA> <ROWDATA/> </DATAPACKET> |
La procédure ci-dessous permet de récupérer un nœud d'un document XML grâce à son nom :
Code Delphi : | Sélectionner tout |
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 26 27 28 29 30 31 32 33 34 35 | function GetNode(XmlNode : IXmlNode;NodeName : String) : IXmlNode; var i : integer; begin Result := nil; //Les nœuds internes sont traités récursivement if XMLNode.NodeType <> ntElement then Exit; //S'il s'agit d'une feuille if XMLNode.IsTextElement then if UpperCase(XmlNode.NodeName) = UpperCase(NodeName) then begin Result := XmlNode; Exit; end; // S'il s'agit d'un attribut for i := 0 to XMLNode.AttributeNodes.Count - 1 do if UpperCase(XMLNode.AttributeNodes.Nodes[I].NodeName) = Uppercase(NodeName) then begin Result := XMLNode.AttributeNodes.Nodes[I]; Exit; end; // Si le nœud a des enfants on recherche dedans. if XMLNode.HasChildNodes then for I := 0 to XMLNode.ChildNodes.Count - 1 do begin Result := GetNode(XmlNode.ChildNodes.Nodes[I],NodeName); // si on a un resultat on quitte car c'est celui qu'on recherche if Result <> nil then Exit; end; end; |
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 | var Noeud : IXmlNode; begin Noeud := GetNode(XmlDoc.DocumentElement,'MonNoeud'); if Assigned(Noeud) then Showmessage(La valeur de ' + Noeud.NodeName + ' est de ' + Noeud.Text); end; |
Voici une fonction qui vous permettra d'obtenir un document résultant de la transformation d'un fichier XML par un XSL.
Code Delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | function FusionXMLXSL(sXML, sXSL: string): string; var XMLDoc1 : TXMLDocument; XSLPageProd1: TXSLPageProducer; begin Result := '' ; try XMLDoc1 := TXMLDocument.Create(Self); XMLDoc1.DOMVendor := DOMVendors.Find ('MSXML'); XSLPageProd1 := TXSLPageProducer.Create(Self); XSLPageProd1.DOMVendor := DOMVendors.Find ('MSXML'); XMLDoc1.LoadFromXML(sXML); XSLPageProd1.XMLData := XMLDoc1; XSLPageProd1.XML.text := sXSL; Result := XSLPageProd1.Content; finally if (XMLDoc1 <> Nil) then XMLDoc1.Free; if (XSLPageProd1 <> Nil) then XSLPageProd1.Free; end; end; |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.