AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

XML parsen, aber wie

Ein Thema von stifflersmom · begonnen am 29. Mär 2017 · letzter Beitrag vom 2. Jul 2021
Antwort Antwort
Seite 4 von 4   « Erste     234
Edelfix

Registriert seit: 6. Feb 2015
Ort: Stadtoldendorf
147 Beiträge
 
Delphi 10.4 Sydney
 
#31

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 14:33
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;
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.811 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#32

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 14:59
Ich lege nach und mache ein vollständiges Beispiel:

Delphi-Quellcode:
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.
mit der importierten XML über den XML Data Binding Wizard (Name der Unit hier mit UID gewählt, kann aber geändert werden):

Delphi-Quellcode:

{***************************************************}
{                                                   }
{                 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.
Ergibt bspw. für den zweiten Button:

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]

Geändert von TiGü (22. Jun 2021 um 15:02 Uhr)
  Mit Zitat antworten Zitat
ioster

Registriert seit: 15. Aug 2008
70 Beiträge
 
Delphi 10.3 Rio
 
#33

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 15:04
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
  Mit Zitat antworten Zitat
ioster

Registriert seit: 15. Aug 2008
70 Beiträge
 
Delphi 10.3 Rio
 
#34

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 15:13
Ich lege nach und mache ein vollständiges Beispiel:

Delphi-Quellcode:
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.
mit der importierten XML über den XML Data Binding Wizard (Name der Unit hier mit UID gewählt, kann aber geändert werden):
Vielen Dank für den ausführlichen Code!! Ich bekomme nach den vielen Tipps aber immer mehr Fragezeichen auf der Stirn, weil ich die Objekte und Methoden überhaupt nicht verstehe und die Hilfe von Embarcadero auch nicht wirklich tiefschürfend ist.

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
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.811 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#35

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 17:15
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.
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.811 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#36

AW: XML parsen, aber wie

  Alt 22. Jun 2021, 17:16
Wenn du eher ein visueller Typ bist:
https://www.youtube.com/results?sear...L+Data+Binding
  Mit Zitat antworten Zitat
ioster

Registriert seit: 15. Aug 2008
70 Beiträge
 
Delphi 10.3 Rio
 
#37

AW: XML parsen, aber wie

  Alt 2. Jul 2021, 09:01
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
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +2. Es ist jetzt 03:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf