XML parsen, aber wie
Moin,
ich habe hier ein XML Ergebnis vom Bundesamt für Steuern und will eigentlich nur den Errorcode haben. Wie würdet Ihr das auseinandernehmen, einen "vollständigen" XML-Parser benutzen oder versuchen mit Pos den Bereich des Errorcodes zu ermitteln?
Code:
<params>
<param> <value><array><data> <value><string>UstId_1</string></value> <value><string>DE1234567889</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>ErrorCode</string></value> <value><string>200</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>UstId_2</string></value> <value><string>IT987654321</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Druck</string></value> <value><string>nein</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Erg_PLZ</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Ort</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Datum</string></value> <value><string>28.03.2017</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>PLZ</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Erg_Ort</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Uhrzeit</string></value> <value><string>15:08:27</string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Erg_Name</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Gueltig_ab</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Gueltig_bis</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Strasse</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Firmenname</string></value> <value><string></string></value> </data></array></value> </param> <param> <value><array><data> <value><string>Erg_Str</string></value> <value><string></string></value> </data></array></value> </param> </params> |
AW: XML parsen, aber wie
Wenn Du wirklich und für alle Zeiten nur den Errorcode brauchst, nimm halt Pos. Mit einem XML-Parser musst Du ja ähnlich vorgehen, nur halt mit anderem Zeug drumrum. Gibt es aber wirklich nur einen Errocode?
Sherlock |
AW: XML parsen, aber wie
Ja, nur einen.
Der kann dann halt bummelig 25 verschiedene Werte aufweisen, aber das war es dann. |
AW: XML parsen, aber wie
Hallo,
das ist ja das betreffende Stück // Startzeile <value><string>ErrorCode</string></value> <value><string>200</string></value> // Endzeile </data></array></value> In dem Fall würde ich das ganze in eine StringList packen, die durchlaufen bis zur Zeile <value><string>ErrorCode</string></value> (Pos()=1) danach den Index an eine zweite Methode übergeben, und die durchläuft die StringList dann bis zum </data></array></value> und holt sich per StringReplace('<value><string>','') und StringReplace('</string></value>','') die Errorcodes Quick&Dirty halt Du solltest bloss vor dem Benutzen einer Zeile (Sche, Ersetzen) ein Trim machen. |
AW: XML parsen, aber wie
Ich hab sowas Ähnliches mit OmniXML und XPath gelöst. Um z.B. aus einer *.groupproj-Datei zu lesen:
Delphi-Quellcode:
function GroupProj_ReadProjects(const AGroupProjName: string; ADProjNames: TStrings): Boolean;
var Doc: IXMLDocument; Root: IXMLElement; CallTargetNode, ProjectNode: IXMLNode; Targets: string; begin Doc := CreateXMLDoc; Doc.PreserveWhiteSpace := False; if not Doc.Load(AGroupProjName) then Exit(False); Root := Doc.DocumentElement; if (Root = nil) or (Root.TagName <> 'Project') then Exit(False); CallTargetNode := Root.SelectSingleNode('Target[@Name=''Build'']/CallTarget'); Targets := CallTargetNode.Attributes.GetNamedItem('Targets').Text; // usw. ... end; |
AW: XML parsen, aber wie
Ausgehend von diesem Post http://www.delphipraxis.net/1365797-post2.html
Statt:
Delphi-Quellcode:
mache mal einfach das:
Try
idHttp1 := TIdHTTP.Create; responseStream := TMemoryStream.Create; Screen.Cursor := crHourGlass; try IdHTTP1.Get(sUrlLong, responseStream); IdHTTP1.Disconnect(True); except on E: EIdException Do FormMain.add_info('UST Abfrage gescheitert '+E.Message); end; SetString(resultstring, PAnsiChar(responseStream.Memory), responseStream.Size); Finally idHttp1.Free; responseStream.Clear; responseStream.Free; Screen.Cursor := crDefault; End;
Delphi-Quellcode:
var sl : TStringList; i : Integer; sErrorCode : String; begin ... Try idHttp1 := TIdHTTP.Create; sl := TStringList.Create; Screen.Cursor := crHourGlass; try sl.Text := IdHTTP1.Get(sUrlLong); IdHTTP1.Disconnect(True); i := sl.IndexOf('<value><string>ErrorCode</string></value>'); if i > -1 then begin sErrorCode := sl[i + 1]; sErrorCode := AnsiReplaceText(sErrorCode,'<value><string>',''); sErrorCode := AnsiReplaceText(sErrorCode,'</string></value>',''); end; except on E: EIdException Do FormMain.add_info('UST Abfrage gescheitert '+E.Message); end; Finally sl.Free; idHttp1.Free; Screen.Cursor := crDefault; End; |
AW: XML parsen, aber wie
Hallo Stefan,
damit bekommt er aber nur den ersten ErrorCode, dass muss eine Schleife sein, wenn ich das so wie unten verstanden habe. <value><string>ErrorCode</string></value> <value><string>200</string></value> <value><string>300</string></value> </data></array></value> |
AW: XML parsen, aber wie
Nein, es gibt nur einmal einen Errorcode und von daher ist Nahpets Lösung sehr intzeressant.
|
AW: XML parsen, aber wie
Ich hoffe das kommt nicht falsch rüber, aber ihr durchsucht wirklich eine XML-Datei wie eine Text-Datei? Entscheidet sich die Gegenstelle einmal irgendwo ein Leerzeichen oder einen Zeilenumbruch woanders zu setzen und schon klappt nichts mehr.
Warum nicht über XML? Kostet doch kein Geld... |
AW: XML parsen, aber wie
XML Parser nehmen fertig. Kostet sicher weniger Entwicklungszeit als eine Textsuche, die auch auf sich ändernde Zeilenumbrüche reagieren kann!
Edit:@ Günther: Es ist echt von Vorteil Threads bis zum Ende zu lesen :-) |
AW: XML parsen, aber wie
Warum versuchen eigentlich ständig Alle auf Biegen und Brechen nicht das zu verwenden, was dafür gedacht ist?
http://stackoverflow.com/questions/3...p-xml-response http://www.office-loesung.de/ftopic312578_0_0_asc.php http://howtoprogram.eu/question/n-a,55664 Bei einer XML auf die Idee zu kommen das mit sonstwas zu parsen ... braucht nur mal die Quelle die XML anders zu Formatieren und schon knallt es, obwohl sich am Inhalt garnichts ändert. Gut, wer krank ist, der kann statt des fehleranfälligen Pos/Copy-Codes es mit einem etwas weniger fehleranfälligen RegEx versuchen. :roll: Aber, auch wenn die Anwort eine XML ist, so ist das ganze eigentlich nur die Rückantwort eines Remote-Procedure-Call Dokumentation: http://evatr.bff-online.de/eVatR/xmlrpc/ Beispiel: http://evatr.bff-online.de/evatrRPC?...trasse=&Druck= Delphi XML RPC |
AW: XML parsen, aber wie
Nu komm mal runter.
Wer arbeitet sich in die Feinheiten von XML ein nur weil alle Jubeljahre mal (zuverlässig) eine Datei vorbei kommt. Insbesondere wenn die notorischen Besserwisser einem im Genick sitzen "das ist doch auch nur eine Textdatei, warum brauchen Sie dann so lange?" Gruß K-H P.S. Dank für die vielen Links, da ist die Mittagspause gerettet. |
AW: XML parsen, aber wie
Hallo,
Zitat:
nehme ich eine StringList und Pos, warum auch nicht? Wenn's funktioniert? Das war jetzt hier als Bsp., und nicht für die Xml des TE, die kommt ja aus der "Fremde". |
AW: XML parsen, aber wie
'ne abgewandelte Version für die, die Angst um veränderte Zeilenumbrüche haben:
Delphi-Quellcode:
Und nun haben wir im Wechesel jeweil Beschreibung und den Text dazu.
var
sl : TStringList; s : String; i : Integer; sErrorCode : String; begin ... Try idHttp1 := TIdHTTP.Create; sl := TStringList.Create; Screen.Cursor := crHourGlass; try s := IdHTTP1.Get(sUrlLong); IdHTTP1.Disconnect(True); // Tags werden vom Inhalt getrennt, indem sie je Tag in eine Zeile kommen s := AnsiReplaceText(s,'<',#13#10 + '<'); s := AnsiReplaceText(s,'>','>' + #13#10); sl.Text := s; // Tags brauchen wir nicht, ebensowenig wie Leerzeilen. for i := sl.Count - 1 downto 0 do begin if (Copy(sl[i],1,1) = '<') or (sl[i] = '') then sl.Delete(i); end; i := sl.IndexOf('ErrorCode'); if i > -1 then sErrorCode := sl[i + 1]; except on E: EIdException Do FormMain.add_info('UST Abfrage gescheitert ' + E.Message); end; Finally sl.Free; idHttp1.Free; Screen.Cursor := crDefault; End; Damit könnte man dann mit wenig Aufwand auch alles in 'ne Datenbank übernehmen. Und ja, es geht auch mit 'nem XML-Parser. |
AW: XML parsen, aber wie
Die Abfrage klingt irgendwie falsch:
Delphi-Quellcode:
Außerdem werden da auch die Endtags (/>) nicht berücksichtigt.
// Tags brauchen wir nicht, ebensowenig wie Leerzeilen.
for i := sl.Count - 1 downto 0 do begin if (Copy(sl[i],1,1) = '<') or (Copy(sl[i],1,1) = '<') or (sl[i] = '') then sl.Delete(i); end; Ich würde auch einen XML-Parser nehmen. Ist initial zwar mehr Aufwand, aber wenn die Formatierung mal eine andere ist, funktioniert es noch. Bei den ganzen Stringreplaces muss nur einmal anstatt <tag></tag> nur ein <tag /> stehen und es geht möglicherweise schon gar nicht mehr. |
AW: XML parsen, aber wie
Oh, da war ein Schreibfehler drinne, muss latürnich
Delphi-Quellcode:
heißen.
// Tags brauchen wir nicht, ebensowenig wie Leerzeilen.
for i := sl.Count - 1 downto 0 do begin if (Copy(sl[i],1,1) = '<') or (sl[i] = '') then sl.Delete(i); end; Alle Zeilen, die mit 'nem < beginnen, fliegen raus, ebenso alle Leerzeilen. Endetags mussen hier nicht separat berücksichtigt werden, weil sie im XML, um das es hier geht, nicht vorkommen. Wir haben hier immer mehr oder weniger viele öffnende Tags. Dann den Inhalt. Dann die entsprechende Anzahl schließender Tags. Wenn nun vor die < und hinter die > jeweils ein Zeilenumbruch eingefügt wird, dann sind alle Tags separiert. Sie und die ggfls. entstehenden Leerzeilen fliegen raus und übrig bleibt der Inhalt. Natürlich ist das nicht auf beliebige XML-Dateien anwendbar, aber danach war auch nicht gefragt. Das "Schöne" an dieser Vorgehensweise: Sie funktioniert auch noch dann, wenn man fehlerhaftes XML bekommt, bei dem "richtige" Parser zu Recht streiken. Mit dieser Vorgehensweise funktioniert seit Jahren meine Suchmaschine für HTML-Seiten. Es ist wurscht, ob die Seiten gültiges HTML enthalten und von Browsern/Parsern richtig oder näherungsweise interpretiert werden können. Als Ergbenis erhalte ich immer ausschließlich den Text der Seiten und kann ihn, nach entsprechender Weiterverarbeitung, in den Suchindex eintragen. |
AW: XML parsen, aber wie
Hallo,
also, wenn das Format der Datei verschieden sein kann, ist die Benutzung von TStringList falscher als ein Xlm-Parser. Wer weiss, was die da alles machen, dass bekommt man mit TStringList gar nicht alles hin (unter Umständen). |
AW: XML parsen, aber wie
Moin...:P
Ich wollte mich eigentlich heraushalten. :wink: Was habt ihr gegen einen XML Parser? (:wink: ausgenommen die die das auch vorgeschlagen haben) Es gibt nicht nur die mit dem Overhead von TXMLDocument...:roll: Beispiel (mit himXML):
Delphi-Quellcode:
...fertsch. 8-)
uses
himXML; ... XML: TXMLFile; ... XML := TXMLFile.Create; ... XML.LoadFromFile(FFileName); //XML.LoadFromStream(Stream); ErrorString := XML.Node['Errors'].Node['ErrorCode'].Text_S; // Beispiele für Node Bezeichnungen :-) |
AW: XML parsen, aber wie
Hallo,
nicht wenn das so aussieht <value><string>ErrorCode</string></value> <value><string>200</string></value> <value><string>300</string></value> </data></array></value> Oder müsste das nicht so aussehen? <value><array><data> <value><string>ErrorCode</string></value> <value><string>200</string></value> <value><string>ErrorCode</string></value> <value><string>300</string></value> </data></array></value ? |
AW: XML parsen, aber wie
Es gibt in einer Antwort des Servers nur einen ErrorCode, nämlich den zu den abgefragten Daten.
Ein Satz kann immer nur einen Fehlercode enthalten sein. Hier jetzt Probleme zu lösen, die nur dann auftreten, wenn man eine nicht der Spezifikation entsprechende Antwort bekommt, halte ich für übertrieben. |
AW: XML parsen, aber wie
Ich hätte nicht gedacht, einen solchen Glaubenskrieg zu entfesseln....
Ich habe mich jetzt für eine sehr überschaubare Lösung mit Entfernen aller Zeilenumbrüche und nschließendem Pos entschieden, war halt einfach schnell zusammen getippt und da die "xml" Datei dieses feste Format aufweist, scheint mir diese Lösung auch durchaus gerechtfertigt zu sein. Danke aber trotzdem für die vielen Vorschläge |
AW: XML parsen, aber wie
Zitat:
Ciao Stefan |
AW: XML parsen, aber wie
Zitat:
Ganz ehrlich, wenn man XML Daten hat, dann nutzt einen XML Parser, auch wenn diese selbst erstellt wurden. Vielleicht finden man ja doch mal einen Fehler, oder aktualisiert die Library, welche man nutzt... Und dann gibt es Probleme. Etwas anderes als einen XML Parser vorzuschlagen ist hier schlicht und ergreifend fahrlässig, insbesondere wenn schon im ersten Post klar wird, dass die Daten von extern kommen... Und um auch noch einen Nutzen dazu zu bringen, wenn das XML Document geladen ist, ist hier die XPath-Query für die Fehlerbeschreibung:
Code:
und den Fehlercode:
//params/param[2]/value/array/data/value[1]/string
Code:
...:cat:...
//params/param[2]/value/array/data/value[2]/string
|
AW: XML parsen, aber wie
Und über einen passende RPC-Objekt-Bibliothek würde in etwa sowas rauskommen.
Delphi-Quellcode:
RPCObject := RPCHandler.GetIrgendwas('DE123456789', 'AB1234567890', '', '', '', ''); // UstId_1, UstId_2, Firmenname, Ort, PLZ, Strasse, Druck
UstId_1 := RPCObject.UstId_1; ErrorCode := RPCObject.ErrorCode; |
AW: XML parsen, aber wie
Moin,
ich muss das hier angesprochene Ursprungsproblem mit der Auswertung der XML-RPC-Schnittstelle des Bundeszentralamtes für Steuern ebenfalls lösen. Bei Betrachtung der Schnittstellenbeschreibung hatte ich angenommen, dass es kein Hexenwerk ist. Nachdem ich nun über die Klippe von TLS 1.2 mit Indy gesprungen bin, suche ich nun nach der Auflösung des Rätsels, wie ich auf die einzelnen Parameter eines XML-Objektes zugreifen kann, wenn es keine klassischen Nodes sondern Params sind. Die Code-Schnipsel, die ich bisher gefunden habe, helfen mir leider nicht weiter, weil ich die Methoden in meiner IDE nicht finden kann. Was hat es mit XPath auf sich und wie kann ich darüber auf die einzelnen Param-Einträge zugreifen? So in etwa sieht das Dokument aus, das von der Schnittstelle zurückgegeben wird: <params> <param> <value><array><data><value><string>UstId_1</string></value> <value><string>DE123456789</string></value></data></array></value> </param> <param> <value><array><data> <value><string>ErrorCode</string></value> <value><string>201</string></value></data></array></value> </param> <param> <value><array><data><value><string>UstId_2</string></value> <value><string>PL123456789</string></value></data></array></value> </param> Viele Grüße Ingo |
AW: XML parsen, aber wie
Es ist doch normale Nodes die zufällig "params" heissen.
|
AW: XML parsen, aber wie
Du solltest am besten einen Link posten wo man sich das XML in ganzer Schönheit anschauen kann.
|
AW: XML parsen, aber wie
Zitat:
Testweise geht aber vielleicht dieser Link. Viele Grüße Ingo |
AW: XML parsen, aber wie
Ich komme über folgenden Code auf 16 Childnodes, die allesamt PARAM als heißen.
Delphi-Quellcode:
Die Werte müsste ich doch nun über AttributeNodes lesen können oder wie muss ich mir das nun vorstellen?
if not(XMLDok.IsEmptyDoc) then
begin for AktNode := 0 to XMLDok.DocumentElement.ChildNodes.Count - 1 do begin : end; end; Gruß Ingo |
AW: XML parsen, aber wie
Ich würde je Knotenebene FindNode und NextSibling verwenden, um durch die Kindknoten derselben Ebene zu navigieren.
|
AW: XML parsen, aber wie
Nicht vollständig aber als Hilfe:
Delphi-Quellcode:
procedure Test1(XMLStr: string);
var XmlDoc: IXmlDocument; Root: IXMLNode; s: string; I: Integer; N1: IXMLNode; N2: IXMLNode; N3: IXMLNode; begin XMLDoc := TXMLDocument.Create(nil); try XMLDoc.XML.Text := XMLStr; XMLDoc.Active := true; Root := XmlDoc.DocumentElement; s := Root.NodeName; // Zum Debugen //-- N1 := Root.ChildNodes.FindNode('params'); for I := 0 to N1.ChildNodes.Count-1 do begin N2 := N1.ChildNodes[i]; if N2.ChildNodes.FindNode('value')<>nil then begin if N2.ChildNodes.FindNode('array')<>nil then // Muss dann natürlich weiter verschachteln begin s := N2.ChildNodes.FindNode('array').Text; end; end; end; end; |
AW: XML parsen, aber wie
Ich lege nach und mache ein vollständiges Beispiel:
Delphi-Quellcode:
mit der importierten XML über den XML Data Binding Wizard (Name der Unit hier mit UID gewählt, kann aber geändert werden):
unit GetUID;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Net.HttpClient, System.Net.URLClient, System.Net.HttpClientComponent, Xml.xmldom, Xml.XMLDoc, Xml.XMLIntf, UID; type TForm3 = class(TForm) btnSampleCall1: TButton; btnSampleCall2: TButton; NetHTTPClient1: TNetHTTPClient; procedure btnSampleCall1Click(Sender: TObject); procedure btnSampleCall2Click(Sender: TObject); private procedure ShowResponse(const URL: string); end; var Form3: TForm3; implementation {$R *.dfm} // https://evatr.bff-online.de/eVatR/xmlrpc/http const SAMPLE1 = 'https://evatr.bff-online.de/evatrRPC?UstId_1=DE123456789&UstId_2=AB1234567890&Firmenname=&Ort=&PLZ=&Strasse='; SAMPLE2 = 'https://evatr.bff-online.de/evatrRPC?UstId_1=DE123456789&UstId_2=AB1234567890&Firmenname=Firmenname einschl. Rechtsform&Ort=Ort der Firma&PLZ=12345&Strasse=Strasse der Firma'; procedure TForm3.btnSampleCall1Click(Sender: TObject); begin ShowResponse(SAMPLE1); end; procedure TForm3.btnSampleCall2Click(Sender: TObject); begin ShowResponse(SAMPLE2); end; procedure TForm3.ShowResponse(const URL: string); var Response: IHTTPResponse; XmlDoc: IXMLDocument; RPCAnswer: UID.IXMLParamsType; Param: UID.IXMLParamType; Value, Value2: UID.IXMLValueType; I, J, K: Integer; DbgStr: string; begin Response := NetHTTPClient1.Get(URL); XmlDoc := NewXMLDocument(); XmlDoc.LoadFromXML(Response.ContentAsString()); RPCAnswer := Getparams(XmlDoc); DbgStr := ''; for I := 0 to RPCAnswer.Count - 1 do begin Param := RPCAnswer.Param[I]; DbgStr := DbgStr + 'Param: ' + I.ToString + Param.Value.String_ + sLineBreak; for J := 0 to Param.Value.Array_.Data.Count - 1 do begin Value := Param.Value.Array_.Data.Value[J]; if Value.String_ <> '' then DbgStr := DbgStr + '....Value ' + J.ToString + ' string: ' + Value.String_ + sLineBreak; // weitere Schachtelungen möglich, hier aber nicht in den beiden Beispielen for K := 0 to Value.Array_.Data.Count - 1 do begin Value2 := Value.Array_.Data.Value[K]; if Value2.String_ <> '' then DbgStr := DbgStr + '.......Value ' + K.ToString + ' string: ' + Value2.String_ + sLineBreak; end; end; end; ShowMessage(DbgStr); end; end.
Delphi-Quellcode:
Ergibt bspw. für den zweiten Button:{***************************************************} { } { XML Data Binding } { } { Generated on: 22.06.2021 13:59:22 } { Generated from: D:\Github-Repos\new 2.xml } { Settings stored in: D:\Github-Repos\new 2.xdb } { } {***************************************************} unit UID; interface uses Xml.xmldom, Xml.XMLDoc, Xml.XMLIntf; type { Forward Decls } IXMLParamsType = interface; IXMLParamType = interface; IXMLValueType = interface; IXMLArrayType = interface; IXMLDataType = interface; { IXMLParamsType } IXMLParamsType = interface(IXMLNodeCollection) ['{F262379E-19C8-4062-BEF9-78826C7E7FF0}'] { Property Accessors } function Get_Param(Index: Integer): IXMLParamType; { Methods & Properties } function Add: IXMLParamType; function Insert(const Index: Integer): IXMLParamType; property Param[Index: Integer]: IXMLParamType read Get_Param; default; end; { IXMLParamType } IXMLParamType = interface(IXMLNode) ['{96DA74CC-1B8A-4368-AA9E-99464D25D589}'] { Property Accessors } function Get_Value: IXMLValueType; { Methods & Properties } property Value: IXMLValueType read Get_Value; end; { IXMLValueType } IXMLValueType = interface(IXMLNode) ['{235C08FA-0EBB-41E4-A7FE-4123BFE0D250}'] { Property Accessors } function Get_String_: UnicodeString; function Get_Array_: IXMLArrayType; procedure Set_String_(Value: UnicodeString); { Methods & Properties } property String_: UnicodeString read Get_String_ write Set_String_; property Array_: IXMLArrayType read Get_Array_; end; { IXMLArrayType } IXMLArrayType = interface(IXMLNode) ['{0A59A8A5-86DD-4D4B-B345-6D553493DC94}'] { Property Accessors } function Get_Data: IXMLDataType; { Methods & Properties } property Data: IXMLDataType read Get_Data; end; { IXMLDataType } IXMLDataType = interface(IXMLNodeCollection) ['{B3867F76-837B-495B-AD2B-ACBCC3B50263}'] { Property Accessors } function Get_Value(Index: Integer): IXMLValueType; { Methods & Properties } function Add: IXMLValueType; function Insert(const Index: Integer): IXMLValueType; property Value[Index: Integer]: IXMLValueType read Get_Value; default; end; { Forward Decls } TXMLParamsType = class; TXMLParamType = class; TXMLValueType = class; TXMLArrayType = class; TXMLDataType = class; { TXMLParamsType } TXMLParamsType = class(TXMLNodeCollection, IXMLParamsType) protected { IXMLParamsType } function Get_Param(Index: Integer): IXMLParamType; function Add: IXMLParamType; function Insert(const Index: Integer): IXMLParamType; public procedure AfterConstruction; override; end; { TXMLParamType } TXMLParamType = class(TXMLNode, IXMLParamType) protected { IXMLParamType } function Get_Value: IXMLValueType; public procedure AfterConstruction; override; end; { TXMLValueType } TXMLValueType = class(TXMLNode, IXMLValueType) protected { IXMLValueType } function Get_String_: UnicodeString; function Get_Array_: IXMLArrayType; procedure Set_String_(Value: UnicodeString); public procedure AfterConstruction; override; end; { TXMLArrayType } TXMLArrayType = class(TXMLNode, IXMLArrayType) protected { IXMLArrayType } function Get_Data: IXMLDataType; public procedure AfterConstruction; override; end; { TXMLDataType } TXMLDataType = class(TXMLNodeCollection, IXMLDataType) protected { IXMLDataType } function Get_Value(Index: Integer): IXMLValueType; function Add: IXMLValueType; function Insert(const Index: Integer): IXMLValueType; public procedure AfterConstruction; override; end; { Global Functions } function Getparams(Doc: IXMLDocument): IXMLParamsType; function Loadparams(const FileName: string): IXMLParamsType; function Newparams: IXMLParamsType; const TargetNamespace = ''; implementation uses Xml.xmlutil; { Global Functions } function Getparams(Doc: IXMLDocument): IXMLParamsType; begin Result := Doc.GetDocBinding('params', TXMLParamsType, TargetNamespace) as IXMLParamsType; end; function Loadparams(const FileName: string): IXMLParamsType; begin Result := LoadXMLDocument(FileName).GetDocBinding('params', TXMLParamsType, TargetNamespace) as IXMLParamsType; end; function Newparams: IXMLParamsType; begin Result := NewXMLDocument.GetDocBinding('params', TXMLParamsType, TargetNamespace) as IXMLParamsType; end; { TXMLParamsType } procedure TXMLParamsType.AfterConstruction; begin RegisterChildNode('param', TXMLParamType); ItemTag := 'param'; ItemInterface := IXMLParamType; inherited; end; function TXMLParamsType.Get_Param(Index: Integer): IXMLParamType; begin Result := List[Index] as IXMLParamType; end; function TXMLParamsType.Add: IXMLParamType; begin Result := AddItem(-1) as IXMLParamType; end; function TXMLParamsType.Insert(const Index: Integer): IXMLParamType; begin Result := AddItem(Index) as IXMLParamType; end; { TXMLParamType } procedure TXMLParamType.AfterConstruction; begin RegisterChildNode('value', TXMLValueType); inherited; end; function TXMLParamType.Get_Value: IXMLValueType; begin Result := ChildNodes['value'] as IXMLValueType; end; { TXMLValueType } procedure TXMLValueType.AfterConstruction; begin RegisterChildNode('array', TXMLArrayType); inherited; end; function TXMLValueType.Get_String_: UnicodeString; begin Result := ChildNodes['string'].Text; end; procedure TXMLValueType.Set_String_(Value: UnicodeString); begin ChildNodes['string'].NodeValue := Value; end; function TXMLValueType.Get_Array_: IXMLArrayType; begin Result := ChildNodes['array'] as IXMLArrayType; end; { TXMLArrayType } procedure TXMLArrayType.AfterConstruction; begin RegisterChildNode('data', TXMLDataType); inherited; end; function TXMLArrayType.Get_Data: IXMLDataType; begin Result := ChildNodes['data'] as IXMLDataType; end; { TXMLDataType } procedure TXMLDataType.AfterConstruction; begin RegisterChildNode('value', TXMLValueType); ItemTag := 'value'; ItemInterface := IXMLValueType; inherited; end; function TXMLDataType.Get_Value(Index: Integer): IXMLValueType; begin Result := List[Index] as IXMLValueType; end; function TXMLDataType.Add: IXMLValueType; begin Result := AddItem(-1) as IXMLValueType; end; function TXMLDataType.Insert(const Index: Integer): IXMLValueType; begin Result := AddItem(Index) as IXMLValueType; end; end.
Code:
[Window Title]
Getuidtest [Content] Param: 0 ....Value 0 string: UstId_1 ....Value 1 string: DE123456789 Param: 1 ....Value 0 string: ErrorCode ....Value 1 string: 212 Param: 2 ....Value 0 string: UstId_2 ....Value 1 string: AB1234567890 Param: 3 ....Value 0 string: Druck ....Value 1 string: nein Param: 4 ....Value 0 string: Erg_PLZ Param: 5 ....Value 0 string: Ort ....Value 1 string: Ort der Firma Param: 6 ....Value 0 string: Datum ....Value 1 string: 22.06.2021 Param: 7 ....Value 0 string: PLZ ....Value 1 string: 12345 Param: 8 ....Value 0 string: Erg_Ort Param: 9 ....Value 0 string: Uhrzeit ....Value 1 string: 14:59:16 Param: 10 ....Value 0 string: Erg_Name Param: 11 ....Value 0 string: Gueltig_ab Param: 12 ....Value 0 string: Gueltig_bis Param: 13 ....Value 0 string: Strasse ....Value 1 string: Strasse der Firma Param: 14 ....Value 0 string: Firmenname ....Value 1 string: Firmenname einschl. Rechtsform Param: 15 ....Value 0 string: Erg_Str [OK] |
AW: XML parsen, aber wie
Wenn ich die Antworten richtig verstehe, gibt es keine Möglichkeit, den String-Wert direkt von der obersten Param-Ebene zu lesen. Ich hatte mir schon eine For-Schleife konstruiert und bin nun auf Childnodes.First und Childnodes.NextSibling umgeschwenkt, um die oberste Ebene mit einer While-Schleife abzuarbeiten. Kommt im Endeffekt wohl auf dasselbe Ergebnis.
Bei Childnodes.Findnode muss ich immer wissen, wie der Name der nächsten Ebene lautet und kann eben nicht bis auf die unterste Ebene direkt zugreifen. Attributes kann ich dann wohl gänzlich aus dem Kreis der Lösungsansätze streichen. Ich muss schauen, ob ich mir nicht eine rekursive Funktion baue, die mir das String-Paar aus der untersten Ebene nach oben zieht. Gruß Ingo |
AW: XML parsen, aber wie
Zitat:
Was hat es mit "RPCAnswer: UID.IXMLParamsType" auf sich? Und was ist der XML Data Binding Wizard und die generierte Datei mit den kryptischen Schlüsseln? Unter Umständen hilft dieser Thread ja künftig auch anderen, die sich mit den Zugriffsmöglichkeiten von Delphi auf ein XMLDocument beschäftigen müssen. Viele Grüße Ingo |
AW: XML parsen, aber wie
Es ist eigentlich ganz stumpf.
Ich habe die Beispiel-XML von der Website abgespeichert und sie dann in Delphi über den besagten XML Data Binding Wizard importiert, der daraus Quelltext strickt. http://docwiki.embarcadero.com/RADSt...rten_verwenden Du schickst einen Request an den Service und erhälst synchron eine Antwort. Dann lädst du aus der Antwort den String mit der XML in ein IXMLDocument und schmeißt das in die Funktion Getparams(). Zurückkonvertiert kommt dann das XML-Document als DOM-Baum, in dem du navigieren kannst. Letztendlich gesehen sind das auch nur Wrapper mit den passenden Bezeichnern um das IXMLDocument herum. |
AW: XML parsen, aber wie
Wenn du eher ein visueller Typ bist:
https://www.youtube.com/results?sear...L+Data+Binding |
AW: XML parsen, aber wie
Moin,
ich möchte mich an dieser Stelle bei allen bedanken, die mir über die Plattform wertvolle Tipps und Codebeispiele zum XML-Problem gesendet haben. Die Überprüfung von USt-ID über das Bundeszentralamt für Steuern konnte ich damit erfolgreich implementieren und unter Umständen hilft mir das auch an anderer Stelle einmal weiter. Viele Grüße Ingo |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:22 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz