Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   XML zum Verzweifeln (https://www.delphipraxis.net/213668-xml-zum-verzweifeln.html)

MyRealName 6. Sep 2023 08:38

XML zum Verzweifeln
 
Ich nehme aber an, dass der Fehler bestimmt vor dem Monitor sitzt...

Ich lese eine XML Datei, recht gross, viele Unterstrukturen und Listen. Jetzt habe ich eine Zubehörliste pro Produkt und würde die Felder gern generisch auslesen.
Der Code, der mich da verwirrt sieht so aus :

Code:
var
  lAccessories: IXMLNodeList;
  lAcc, lChild: IXMLNode;
begin

      lAccessories := lItem.ChildNodes.FindNode('accessory_list').ChildNodes; // findet er
      lAcc := lAccessories.First;
      while Assigned(lAcc) do
      begin
        CodeSite.Send(csmLevel1, '', lAcc.ChildNodes.Count ); // Codesite schreibt 36

        lChild := lAcc.ChildNodes.First;
        while Assigned(lChild) do
        begin
          CodeSite.Send(csmLevel1, lChild.NodeName, VarToStr(lChild.NodeValue));
          lChild := lChild.NextSibling;
        end;

        lAcc := lAcc.NextSibling;
      end;

end;
Das ist nur ein Code-Snippet, also Öffnen und die oberen Ebenen durchzugehen ist da nicht dabei..

Beim Durchlaufen kommt "natürlich" ein Fehler (sonst wäre es ja auch langweilig) :

---------------------------
Debugger Exception Notification
---------------------------
Project Import.exe raised exception class EXMLDocError with message 'Element "alternative_info" does not contain a single text node'.
---------------------------
Break Continue Copy Help
---------------------------

Hier mal ein Stück des XML

Code:
<accessory_item>
<item_id>-2761267905524739048</item_id>
<identification>1[1]</identification>
<item_number/>
<item_subnumber>1</item_subnumber>
<item_number_architect/>
<item_number_internal/>
<item_number_online/>
<item_piece_number_list/>
<sorting_indicator>t</sorting_indicator>
<harmonized_system_code_number/>
<article_for_sale_number>NKM02</article_for_sale_number>
<article_for_sale_number_internal>NKM02</article_for_sale_number_internal>
<item_piece>1</item_piece>
<short_description>NKM02 - Listwa transportowa</short_description>
<internal>true</internal>
<price_representation>price_charged_in_jumbo</price_representation>
<print_image>false</print_image>
<material_groups_key>Transport</material_groups_key>
<commission_groups_key/>
<revenue_accounts_description>STD</revenue_accounts_description>
<F_A_cost_centres_key/>
<ce_text_list/>
<alternative_info>                                                   <--- hier crasht er
<alternative>false</alternative>
</alternative_info>
<amendment_info>
<amendment>false</amendment>
</amendment_info>
<needs_info>
<as_needed>false</as_needed>
</needs_info>
<related_info>
<taken_from_previous>false</taken_from_previous>
</related_info>
Nun die Frage:

Woran erkenne ich solche Elemente, die dann "Unterelemente" haben ? Nodetype ist es nicht, ist immer die gleiche Ord-Zahl von 1

MyRealName 6. Sep 2023 09:17

AW: XML zum Verzweifeln
 
So, habe jetzt rausgefunden, dass ich ein Element wie das "<ce_text_list/>" über IsTextElement=False + ChildNodes.Count = 0 rausfiltern kann (haben ja keinen Wert).
Die Unterlisten gehen dann über IsTextElement=False + ChildNodes.Count > 0

peterbelow 6. Sep 2023 12:11

AW: XML zum Verzweifeln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von MyRealName (Beitrag 1526530)
So, habe jetzt rausgefunden, dass ich ein Element wie das "<ce_text_list/>" über IsTextElement=False + ChildNodes.Count = 0 rausfiltern kann (haben ja keinen Wert).
Die Unterlisten gehen dann über IsTextElement=False + ChildNodes.Count > 0

Hast Du mal versucht, mit dem XML Data Binding Wizard aus der XML-Datei (oder besser dem zugehörigen XML Schema, wenn verfügbar) ein Objektmodell zu generieren? Sowas macht die Arbeit mit XML Dateien sehr viel einfacher, jedenfalls wenn man immer Dateien mit dem gleichen Aufbau verarbeiten muss.

MyRealName 6. Sep 2023 12:20

AW: XML zum Verzweifeln
 
Ich habe eine Pro-Version von Delphi (vom Arbeitgeber gestellt), da gibt es diesen Punkt nicht... :(

peterbelow 6. Sep 2023 12:30

AW: XML zum Verzweifeln
 
Zitat:

Zitat von MyRealName (Beitrag 1526544)
Ich habe eine Pro-Version von Delphi (vom Arbeitgeber gestellt), da gibt es diesen Punkt nicht... :(

Ich hab D11 Pro und da ist der Wizard definitiv dabei. Außerdem gibt es eine verbesserte Version in GetIt zum Download, soweit ich mich erinnere.

MyRealName 6. Sep 2023 12:37

AW: XML zum Verzweifeln
 
Danke, ich schau mal daheim in der Installation, weil im Büro sehe ich es nicht und GetIt funktioniert hier nicht (wohl irgendwas im Proxy falsch konfiguriert).

Stolle58 6. Sep 2023 12:46

AW: XML zum Verzweifeln
 
Ich hab Delphi 10.4 Pro und habe ebenfalls diesen Wizard.
Nur ist er gegenüber früher, in der Kategorie Web und nicht in XML zu finden.

MyRealName 6. Sep 2023 13:20

AW: XML zum Verzweifeln
 
Ich habe jetzt im Endeffekt eine lauffähige rekursive Funktion, die den Namen des Unterlementes an den Parent-Namen (mit Punkt getrennt) anhängt. Das ganze wird

Code:
procedure IterateNode(ARoot: IXMLNode; ACurrentNodeName: String = '');
var
  lChild: IXMLNode;
  lNodeName: String;
begin
  lNodeName := IfThen(ACurrentNodeName <> '', ACurrentNodeName + '.', '');

  lChild := ARoot.ChildNodes.First;
  while Assigned(lChild) do
  begin
    if Not lChild.IsTextElement then
    begin
      if lChild.ChildNodes.Count > 0 then
      begin
        if DoIterate(lChild.NodeName) then
        begin
          CodeSite.EnterMethod(lChild.NodeName);
          IterateNode(lChild, lNodeName + lChild.NodeName);
          CodeSite.ExitMethod(lChild.NodeName);
        end;
      end;
    end else begin
      CodeSite.Send(csmLevel1, lNodeName + lChild.NodeName, VarToStr(lChild.NodeValue));

    end;
    lChild := lChild.NextSibling;
  end;
end;
Im Codesite wird das dann als Baum ausgegeben, leere Elemente werden unterdrückt. Dazu gibt es noch einen Aufruf von DoIterate, der Falsxe zurückliefert, wenn etwas nicht durchgegangen werden soll (ich muss einige Sachen gesondert behandeln).

Jedenfalls ist es eine lauffähige Lösung, damit der Thread auch einen Abschluss hat :)

himitsu 6. Sep 2023 13:44

AW: XML zum Verzweifeln
 
https://www.embarcadero.com/docs/rad...ure-matrix.pdf
XML Bindings nur in Enterprise/Architect.

peterbelow 6. Sep 2023 17:20

AW: XML zum Verzweifeln
 
Zitat:

Zitat von himitsu (Beitrag 1526553)
https://www.embarcadero.com/docs/rad...ure-matrix.pdf
XML Bindings nur in Enterprise/Architect.

Da geht es um was anderes, Tools um XML in datasets zu bekommen und zu exportieren. Der von mir angesprochene Wizard ist definitiv in der Pro-Version dabei, seit vielen Versionen.

WiPhi 7. Sep 2023 06:52

AW: XML zum Verzweifeln
 
Eine aufgepette Version des Databinding-Assistenten findet man auch hier:

https://github.com/MvRens/x2xmldatabinding

Diese unterstützt ein bisschen mehr als der Assistent in Delphi.

MyRealName 11. Okt 2023 13:28

AW: XML zum Verzweifeln
 
Ich habe das XML Databinding gefunden, das Problem war im Endeffekt, dass man dazu ein offenes Projekt haben muss.
Nun hat mir der Wizard 3 Funktionen in den erstellten Sourcecode mit reingegeben :

function GetORDER(Doc: IXMLDocument): IXMLORDERType;
function LoadORDER(const FileName: string): IXMLORDERType;
function NewORDER: IXMLORDERType;

(ORDER ist wohl der 1. Knoten...)

Nun die Frage... Sollte ich das Daten ändern wollen und das ganze wieder als XML speichern wollen, gibt es da auch eine Möglichkeit oder muss ich alles selbst machen und durch-iterieren ?

Edit: Kann man vllt den Start-Knoten "einfach" der Rootnode eines TXMLDocument zuweisen und los geht's ?

peterbelow 11. Okt 2023 18:03

AW: XML zum Verzweifeln
 
var
LOrder: IXMLOrderType;

LOrder.OwnerDocument.XML.Text sollte Dir den kompletten Inhalt des Baums als String liefern und den kannst Du dann in eine Datei schreiben. Dabei bitte das korrekte Encoding (normalerweise UTF-8) beachten.

MyRealName 12. Okt 2023 05:53

AW: XML zum Verzweifeln
 
Zitat:

Zitat von peterbelow (Beitrag 1527987)
var
LOrder: IXMLOrderType;

LOrder.OwnerDocument.XML.Text sollte Dir den kompletten Inhalt des Baums als String liefern und den kannst Du dann in eine Datei schreiben. Dabei bitte das korrekte Encoding (normalerweise UTF-8) beachten.


Danke, das geht, nutze allerdings

LOrder.OwnerDocument.SaveToFile...

MyRealName 13. Okt 2023 07:46

AW: XML zum Verzweifeln
 
So, ich will den Thread damit schliessen, dass ich kurz über die Fallstricke, und wie ich sie gelöst habe, schreibe, damit andere auch eine zufriedenstellende Lösung finden können.
Ich habe, wie gesagt wurde, den XML Data Binding Wizard genutzt, um die XML Datei einzulesen. Diese nutzte Namespaces, die natürlich nicht eingelesen wurden.
Nodes wie dieser
Code:
<bmecat:NAME2>Nebenstelle 2</bmecat:NAME2>
wurden zwar eingefügt, aber ohne "bmecat" Namespace.
Ich habe dazu die erzeugten Klassen erweitert :
Delphi-Quellcode:
function TXMLADDRESSType.Get_NAME2: UnicodeString;
begin
  Result := ChildNodes['bmecat:NAME2'].Text;
end;

procedure TXMLADDRESSType.Set_NAME2(const Value: UnicodeString);
begin
  if Value <> EmptyStr then
    ChildNodes['bmecat:NAME2'].NodeValue := Value;
end;
Dazu musste der Namespace aber entsprechend registriert werden, dies habe ich dann in der erstellen Funktion NewORDER gemacht (der Name kann bei anderen Klassen abweichen, ORDER war in meinem Fall der Rootnode.
Delphi-Quellcode:
function NewORDER: IXMLORDERType;
begin
  Result := NewXMLDocument.GetDocBinding('ORDER', TXMLORDERType, TargetNamespace) as IXMLORDERType;
  Result.Version := '2.1';
  Result.DeclareNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance'); // von mir hinzugefügt
  Result.DeclareNamespace('xsd', 'http://www.w3.org/2001/XMLSchema');          // von mir hinzugefügt
  Result.DeclareNamespace('bmecat', 'http://www.bmecat.org/bmecat/2005');      // von mir hinzugefügt
end;
Jetzt gab es noch einen weiteren Fallstrick und zwar die Attribute in Verbindung mit Namespaces, wie hier :
Code:
<bmecat:PARTY_ID type="supplier_specific">0000055905</bmecat:PARTY_ID>
Dazu musste zum einen im erzeugten Delphi Code, wo der Node erzeugt wird, eine Änderung gemacht werden :
Delphi-Quellcode:
procedure TXMLPARTYType.AfterConstruction;
begin
  RegisterChildNode('bmecat:PARTY_ID', TXMLPARTY_IDType, 'http://www.bmecat.org/bmecat/2005');
  inherited;
end;

function TXMLPARTYType.Get_PARTY_ID: IXMLPARTY_IDType;
begin
  Result := ChildNodes['bmecat:PARTY_ID'] as IXMLPARTY_IDType;
end;
Dort wurde zum einen vor PARTY_ID jeweils "bmecat:" hinzugefügt, zum anderen aber auch in RegisterChildNode noch der 3. Parameter mit der bmecat-URL angegefügt.
Beim Beschreiben des Nodes wurde dann aber anstelle der einfachen Zuweisung wie
Delphi-Quellcode:
var
  lParty: IXMLPARTYType;
begin
  lParty := FXMLOrder.ORDER_HEADER.ORDER_INFO.PARTIES.Add;
  lParty.ADDRESS.NAME2 := AName2;
end;
dann der Node eher händisch erzeugt
Delphi-Quellcode:
var
  lParty: IXMLPARTYType;
  lNode: IXMLNode;
begin
  lParty := FXMLOrder.ORDER_HEADER.ORDER_INFO.PARTIES.Add;
  lNode := lParty.PARTY_ID;
  lNode.Attributes['type'] := ATTR_SUPPLIER_SPECIFIC;
  lNode.Text := ASupplierId;
end;
Beim Einlesen eines XML in die ereugten Objecte gibt es keine Probleme, aber falls man ein komplett neues XML-Dokument in diesem Standard erzeugen will muss man diese Umwege scheinbar gehen. Ist nicht so schlimm, muss man nur wissen ;)

Ich hoffe es hilft, zu dem Thema auch eine abschliessende Lösung zu haben...

WiPhi 13. Okt 2023 13:17

AW: XML zum Verzweifeln
 
Zitat:

Zitat von MyRealName (Beitrag 1528034)
So, ich will den Thread damit schliessen, dass ich kurz über die Fallstricke, und wie ich sie gelöst habe, schreibe, damit andere auch eine zufriedenstellende Lösung finden können.
Ich habe, wie gesagt wurde, den XML Data Binding Wizard genutzt, um die XML Datei einzulesen. Diese nutzte Namespaces, die natürlich nicht eingelesen wurden.
Nodes wie dieser
Code:
<bmecat:NAME2>Nebenstelle 2</bmecat:NAME2>
wurden zwar eingefügt, aber ohne "bmecat" Namespace.

Meinen Beitrag unter #11 hast du dir angeschaut?

Dieses kleine Tool unterstützt Namespaces im vollen Umfang, beim Erstellen und auch beim Lesen von XML Dateien.

MyRealName 14. Okt 2023 07:22

AW: XML zum Verzweifeln
 
Ja, hatte ich, brachte bei mir aber einen Fehler und hatte es zur Seite gelegt. Dann hab ich später eine andere XML Datei gehabt, da ging der Standard Delphi Wizard, hab aber das von Dir gezeigt Tool nicht mehr probiert. Asche auf mein Haupt. Ich teste es nochmal. Danke für den Hinweis


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 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