Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi MSXML-Parser, aber welcher? (https://www.delphipraxis.net/143611-msxml-parser-aber-welcher.html)

AndiOnline 19. Nov 2009 09:21


MSXML-Parser, aber welcher?
 
Hallo

ich arbeite unter Delphi 2009 mit TXMLDocument und der xml-Datenbindung von Delphi. Als DOMVendor
ist MSXML eingestellt. Jetzt würde mich mal interessieren welchen MSXML-Parser Delphi verwendet.
Auf dem System ist MSXML4 und die akt. Version MSXML6 installiert. Delphi bindet bei mir die Unit
msxmldom in mein Projekt ein. Dort habe ich folgenden Code gefunden :

const
{ GUID's from MSXML2_TLB.pas }
CLASS_DOMDocument26: TGUID = '{F5078F1B-C551-11D3-89B9-0000F81FE221}';
CLASS_DOMDocument30: TGUID = '{F5078F32-C551-11D3-89B9-0000F81FE221}';
CLASS_DOMDocument40: TGUID = '{88D969C0-F192-11D4-A65F-0040963251E5}';

function TryObjectCreate(const GuidList: array of TGuid): IUnknown;
var
I: Integer;
Status: HResult;
begin
Status := S_OK;
for I := Low(GuidList) to High(GuidList) do
begin
Status := CoCreateInstance(GuidList[I], nil, CLSCTX_INPROC_SERVER or
CLSCTX_LOCAL_SERVER, IDispatch, Result);
if Status = S_OK then Exit;
end;
OleCheck(Status);
end;

function CreateDOMDocument: IXMLDOMDocument;
begin
Result := TryObjectCreate([CLASS_DOMDocument40, CLASS_DOMDocument30,
CLASS_DOMDocument26, msxml.CLASS_DOMDocument]) as IXMLDOMDocument;
if not Assigned(Result) then
raise DOMException.Create(SMSDOMNotInstalled);
end;

Bedeutet dies nun, dass unter Delphi 2009 grundsätzlich (bei MSXML) mit dem MSXML4-Parser
gearbeitet wird? Wenn ja, wie kann man den akt. MSXML6-Parser einbinden?

Gruß Andi

Alaitoc 19. Nov 2009 09:57

Re: MSXML-Parser, aber welcher?
 
Also wenn ich mich recht entsinne konnte ich MSXML6 zumindest unter Delphi 7 im Menü unter "Projekt\Typbibliothek importieren..." installieren, dabei wurd dann dementsprechend eine Unit für MSXML6 erstellt. Die konnte ich dann halt dementsprechend in mein Projekt einbinden, wobei ich mir dafür dann noch ne WrapperKlasse geschrieben hatte.

Ich schau aber gleich mal in der Pause nach wo das in Delphi 2k9 ist.

MfG Alaitoc

mjustin 19. Nov 2009 10:00

Re: MSXML-Parser, aber welcher?
 
Könnte man das nicht einfach hinzufügen?

CLASS_DOMDocument60: TGUID = '{88D96A05-F192-11D4-A65F-0040963251E5}';

himitsu 19. Nov 2009 10:04

Re: MSXML-Parser, aber welcher?
 
TXMLDocument nimmt die MSXML-Version, welche es als erstes findet,
also von denen, welche in dieser Liste stehen.

Bei dir wäre es also die Version 4.0,
es sei denn du erstellst dir selber die gewünschte Version ... du müßtest dann nur deine eigene Funktion nutzen

Delphi-Quellcode:
const CLASS_DOMDocument: TGUID = '{2933BF90-7B36-11D2-B20E-00C04F983E60}';

function CreateDOMDocument: IXMLDOMDocument;
begin
  Result := TryObjectCreate([CLASS_DOMDocument60, CLASS_DOMDocument40, CLASS_DOMDocument30,
    CLASS_DOMDocument26, msxml.CLASS_DOMDocument]) as IXMLDOMDocument;
  if not Assigned(Result) then
    raise DOMException.Create(SMSDOMNotInstalled);
end;
oder
Delphi-Quellcode:
var XML: IXMLDOMDocument;
OleCheck(CoCreateInstance(CLASS_DOMDocument60, nil, CLSCTX_INPROC_SERVER or
  CLSCTX_LOCAL_SERVER, IDispatch, XML));

Alaitoc 19. Nov 2009 10:11

Re: MSXML-Parser, aber welcher?
 
Naja und es erstellt dann halt "nur" ein IXMLDomDocument, also ohne Funktionalitäten von z.b. MSXML6.
Da würde das IXMLDomDocument3 gebraucht soweit ich mich erinnern kann...

Wobei ich halt immer mit DOMDocument60 und CoDOMDocument60 gearbeitet habe, da hatte ich dann auch 100% alle Funktionalitäten fürs Validieren mit Schemas etc...

MfG Alaitoc

Alaitoc 19. Nov 2009 11:20

Re: MSXML-Parser, aber welcher?
 
Unter Delphi 2k9 kann man die Typbibiliothek über "Komponente\Komponente importieren" hinzufügen.
Einfach im Assistenten "Typbibliothek importieren" auswählen und dann nach MSXML suchen und die
gewünschte Version auswählen.

Damit sollte man zumindest mehr Möglichkeiten haben als mit der TXMLKomponente.

Wichtig: Der Anwender muss natürlich die dementsprechende Version auf dem Rechner haben.

Das kann man z.b. mit dieser Funktion feststellen, die ich irgendwo hier im Forum gefunden habe...

Leider vergessen wo genau her ^_° und bin mir nicht sicher ob man Änderungen für Delphi 2k9 dran vornehmen muss...

Delphi-Quellcode:

unit MSXMLCheck;

interface

uses SysUtils, Registry, Windows, Dialogs, MSXML6_TLB;

function CheckMSXML60:Boolean;
function CheckMSXML40:Boolean;
function CheckMSXML30:Boolean;
function CheckMSXML26:Boolean;

implementation

//**************************************************************************************
//  Überprüfen der angegebenen MSXML Version durch die Registry
//**************************************************************************************

function ExpandEnvStr(const sInput: string): string;
const
  MAXSIZE = 32768;
begin
  SetLength(Result,MAXSIZE);
  SetLength(Result,
            ExpandEnvironmentStrings //The ExpandEnvironmentStrings function expands environment-variable strings and replaces them with their defined values.
              (pchar(sInput),        // LPCTSTR lpSrc = pointer to string with environment variables
              @Result[1],            // LPTSTR lpDst = pointer to string with expanded environment variables
              length(Result)));      // DWORD nSize = maximum characters in expanded string
end;

function DoesMSXMLExist(CLASS_DOMDocument:TGUID): boolean;
var
  reg : TRegistry;
  s  : string;
begin
  Result := false;

  reg   := TRegistry.Create(KEY_READ);
  if(reg <> nil) then
    with reg do
    begin
      try
        RootKey := HKEY_CLASSES_ROOT;
        if(OpenKey('CLSID\' + GuidToString(CLASS_DOMDocument) + '\InProcServer32',false)) then
        try
          s     := ReadString('');
          Result := fileexists(ExpandEnvStr(s));
        finally
          CloseKey;
        end;
      finally
        Free;
      end;
    end;
end;

//**************************************************************************************
//  Überprüfen (MSXML 6.0)
//**************************************************************************************

function CheckMSXML60:Boolean;
begin
  result:=DoesMSXMLExist(CLASS_DOMDocument60);
end;

//**************************************************************************************
//  Überprüfen (MSXML 4.0)
//**************************************************************************************

function CheckMSXML40:Boolean;
begin
  result:=DoesMSXMLExist(CLASS_DOMDocument40);
end;

//**************************************************************************************
//  Überprüfen (MSXML 3.0)
//**************************************************************************************

function CheckMSXML30:Boolean;
begin
  result:=DoesMSXMLExist(CLASS_DOMDocument30);
end;

//**************************************************************************************
//  Überprüfen (MSXML 2.6)
//**************************************************************************************

function CheckMSXML26:Boolean;
begin
  result:=DoesMSXMLExist(CLASS_DOMDocument26);
end;

end.

himitsu 19. Nov 2009 11:27

Re: MSXML-Parser, aber welcher?
 
Bei D2009/D2010 sollte es keine Probleme geben (zumindestens sieht alles gut so aus)

MSXMLCheck ... sollte es nicht eigentlich auch reichen, wenn man einfach mal versucht die verschiedenen Versionen zu erzeugen?

Delphi-Quellcode:
Uses ActiveX, MSXML;

Type TXMLDOMVersion = (xvXX, xv26, xv30, xv40, xv50, xv60);
  TXMLDOMVersions = Set of TXMLDOMVersion;

// xvXX in WinXP = xv30

Function CheckXMLDOMVersion: TXMLDOMVersions;
  Const DOMVer: Array[TXMLDOMVersion] of TGUID = (
      '{2933BF90-7B36-11D2-B20E-00C04F983E60}' {msxml.CLASS_DOMDocument},
      '{F5078F1B-C551-11D3-89B9-0000F81FE221}' {msxmldom.CLASS_DOMDocument26},
      '{F5078F32-C551-11D3-89B9-0000F81FE221}' {msxmldom.CLASS_DOMDocument30},
      '{88D969C0-F192-11D4-A65F-0040963251E5}' {msxmldom.CLASS_DOMDocument40},
      '{88D969E5-F192-11D4-A65F-0040963251E5}' {CLASS_DOMDocument50},
      '{88D96A05-F192-11D4-A65F-0040963251E5}' {CLASS_DOMDocument60});

  Var v: TXMLDOMVersion;
    XML: IXMLDOMDocument;

  Begin
    Result := [];
    For v := Low(v) to High(v) do
      If Succeeded(CoCreateInstance(DOMVer[v], nil, CLSCTX_INPROC_SERVER
          or CLSCTX_LOCAL_SERVER, IDispatch, XML)) Then
        Include(Result, v);
  End;
(wollte eigentlich in dem Array die vordefinierten "Konstanten" verwenden, aber da es typisierte Konstanten sind, sind sie ja eigentlich "Variablen" :wall: )

Alaitoc 19. Nov 2009 11:48

Re: MSXML-Parser, aber welcher?
 
Naja ist halt so die Sache welche Version man brauch...
In meinem Editor zum Beispiel brauch man umbedingt die MSXML Version 6, da nur diese
vollständig die Validierung mit Schemas unterstützt.
Ich glaub bei der MSXML Version 4 war es auch möglich zu validieren, jedoch hat er nur
einen Validierungs-Fehler angezeigt...

Leider zeigt MSXML auch nur immer den ersten Parse-Fehler an und bricht dann ab. Da hab ich
leider noch keine einfache Lösung für gefunden...

Wenn man die TXML-Komponente verwendet ist es aber im Endeffekt egal welche MSXML Version man auf dem Rechner hat, solange man zumindest die 2.6er installiert hat. Sie bietet dafür aber auch meines Wissens nach nur wirklich die Standard - Funktionalitäten.

MfG Alaitoc

himitsu 19. Nov 2009 12:34

Re: MSXML-Parser, aber welcher?
 
Vielleicht findest du dort ja noch ein paar Tipps/Hinweise/Ideen:
http://www.delphipraxis.net/internal...t.php?p=998360
http://forum.fachinformatiker.de/net...en-vb-net.html

Alaitoc 19. Nov 2009 12:59

Re: MSXML-Parser, aber welcher?
 
Leider bin ich beim ersten Link der letzte Poster ^_° und
beim anderen handelt es sich ja um .Net Klassen.

Naja zur Zeit ist es zum Glück nicht nötig mehr Funktionalität einzubauen,
da der Editor für Testzwecke diente und halt für meine Wrapperklasse war und
ich sonst ne Wrapperklasse für die 2.6er Version für einen Parser geschrieben hatte.

Da meckert der Parser nu schon selbstständig, wenn was nicht korrekt ist *gg*.

Aber trotzdem Danke :)

@TE: Falls es noch Fragen zu MSXML gibt, wenn du die Typbibliotheken nutzt kannst du mich gerne anschreiben. Hab im Laufe meiner Recherchen eine umfangreiche Linksammlung zusammengestellt :-D

MfG Alaitoc

himitsu 19. Nov 2009 13:10

Re: MSXML-Parser, aber welcher?
 
Die Codes dort genannten Codes sollten sich doch auch in Delphi umsetzen lassen?
http://msdn.microsoft.com/en-us/library/ms753779.aspx
http://social.msdn.microsoft.com/for...f-653691edc4cc

Alaitoc 19. Nov 2009 13:19

Re: MSXML-Parser, aber welcher?
 
Achso ja gut , mehrere Validierungsfehler zu ermitteln sind nicht "mehr" das Problem.
Da war noch das Problem das ich soweit ich mich recht erinner :gruebel: nicht die Position der Fehler ausgeben konnte...

Das Problem mit den mehreren Fehlern war bei dem Parsevorgang, also allgemeine XML-Kompatibilität. Da bricht MSXML ( eigentlich sinnvollerweise ) bei dem ersten Parsefehler halt ab und gibt nur diesen aus...wobei ich dabei am liebsten alle Parse-Fehler sehen würde...

Wenn ich z.b. eine neue Datei in meinem Editor erstelle und dort irgendwas reinklatsche, dann würde er mir nur den ersten Parse-fehler anzeigen und erst wenn ich den korrigiert habe den nächsten Fehler.
Natürlich könnte man sich da mit viel Aufwand etwas eigenes basteln...jedoch ist das zur Zeit leider nicht drin ^_^


Also

Parsefehler = Fehler während des Parsevorgangs.
Validierungsfehler = Fehler während der Validierung mit einem Schema.

MfG Alaitoc

Anmerkung an mich selbst: Erst immer alles ganz genau lesen...

himitsu 19. Nov 2009 13:40

Re: MSXML-Parser, aber welcher?
 
Zitat:

wobei ich dabei am liebsten alle Parse-Fehler sehen würde...
OK, daß er bei Parsefehlern abbricht ist schon OK, denn ansonsten würde man vermutlich Folgefehler erhalten, welche Keine sind oder einige andere Fehler könnten übersehn werden.
z.B. wenn ein > vergessen wurde oder zuviel vorhanden ist, dann stimmt danach fast nix mehr, vorallem bei den Node-Verschachtelungen.

War auch schon kurz davor, solche bei meinem himXML mit anzeigen zu wollen, aber hab es aus oben genanntem Grund dann gelassen.
Das Einzige wo sowas möglich/sinnvoll wäre, wenn es ein reparierender Parser wäre,
also einer, welcher Fehler versucht zu ignorieren und dann dieses entpsrechend zu behandeln/reparieren.
(wie z.B. die HTML-Parser den Browsern)

Alaitoc 19. Nov 2009 13:46

Re: MSXML-Parser, aber welcher?
 
Jepp stimmt schon, wäre halt nur schön gewesen wenn man es sich in gewisser Weise aussuchen könnte.
Naja manchmal kann man nicht alles haben ^^ ... habe es ja wenigstens hingekriegt das die Validierungsfehler
angezeigt wurden, wobei das auch viel Arbeit war ... zumindest nachträglich das Dokument mit denen zu verknüpfen ohne Änderungen an den Knoten zu machen. Jedoch fehlt da halt die Positionsangabe.

MfG Alaitoc

AndiOnline 20. Nov 2009 10:45

Re: MSXML-Parser, aber welcher?
 
Zitat:

Zitat von Alaitoc
Unter Delphi 2k9 kann man die Typbibiliothek über "Komponente\Komponente importieren" hinzufügen.
Einfach im Assistenten "Typbibliothek importieren" auswählen und dann nach MSXML suchen und die
gewünschte Version auswählen.

Damit sollte man zumindest mehr Möglichkeiten haben als mit der TXMLKomponente.
[/delphi]

Zitat:

Zitat von Alaitoc
Wenn man die TXML-Komponente verwendet ist es aber im Endeffekt egal welche MSXML Version man auf dem Rechner hat, solange man zumindest die 2.6er installiert hat. Sie bietet dafür aber auch meines Wissens nach nur wirklich die Standard - Funktionalitäten.

Ich benutze die TXMLDocument-Komponente und validiere damit die xml-Datei mit einem Schema. Über die Datenbindung (GetDocBinding) kann ich dann sehr einfach auf die Werte zugreifen. Das funktioniert auch soweit sehr gut.

Wenn ich das jetzt richtig verstanden habe :
Benutze ich die TXMLDocument-Komponente wird max. der MSXML4.0-Parser von Delphi verwendet (siehe Eingangspost).
Will ich MSXML6 verwenden, muss ich eine neue Typbibliothek importieren und Komponenten, bzw. Objekte aus dieser Datei verwenden.

Das heißt dann auch, ich muss in meinem Fall bei Verwendung der TXML-Komponente nur darauf achten, dass der Anwender am besten MSXML4.0 installiert hat (hier funktioniert die Validierung mit einem Schema), und muss eigentlich nicht auf MSXML 6.0 updaten (nach dem Motto : never change a running system...?)

Gruß Andi

himitsu 20. Nov 2009 12:57

Re: MSXML-Parser, aber welcher?
 
Um TXMLDocument mit MSXML 6.0 nutzen zu können müßte man doch nur irgendwie (z.B. über XML.DOMVendor) den CLASS_DOMDocument60 übergeben.
Die älteren Basisinterfaces dürften doch auf die neuere Version anwendbar sein ... nur daß eben einige Neuerungen nicht direkt nutzbar wären, da sie ja unbekannt sind.

Alaitoc 20. Nov 2009 15:53

Re: MSXML-Parser, aber welcher?
 
Genau theorethisch möglich, weil man ( eigentlich) aber nicht mehr Funktionen als mit der MSXML 4.0 Version hat, da da scheinbar die TXMLDocument - Komponente drauf aufgelegt ist, kann man sich das mit der MSXML 6.0 Version auch sparen.

Wirkliche Änderungen sollten dabei nicht sichtbar sein, weil die älteren Basisinterfaces ja nicht die neuen Funktionen kennen. Was ich mir vorstellen könnte und vielleicht irgendwo in meiner Linksammlung verborgen ist ^_° , dass es z.b. weniger Sicherheitslücken oder so gibt. Jedoch kann ich da atm nur spekulieren...

Mein Fazit: Im Endeffekt ist es bei der TXMLDocument - Komponente nicht nötig auf MSXML 6.0 umzusteigen.


MSXML 6.0 sollte nur interessant sein wenn man z.b. über die Typenbibliothek arbeitet und die neuen Funktionen benötigt.

MfG Alaitoc

shmia 23. Nov 2009 13:04

Re: MSXML-Parser, aber welcher?
 
Nach meinen Erfahrungen sind nur die Versionen 4 und 6 brauchbar.
Version 3 hat zu wenig Funktionalität und zuviele Bugs (z.B. funktioniert XMLHTTPRequest nicht immer richtig).
Bei MSXML 4.0 sollte man auf jeden Fall das SP3 installieren (und zuvor SP1 und SP2 deinstallieren).
Ohne Servicepack kann es passieren, dass z.B. das Attribut xmlns doppelt geschrieben wird,
was natürlich tödlich für den folgenden Parser ist.

stahli 10. Aug 2010 21:35

AW: MSXML-Parser, aber welcher?
 
Ich will das Thema nochmal aufgreifen:

Für meine ersten Versuche nutze ich derzeit eine TXMLDocument (da man die schnell mal auf den Designer ziehen kann :wink:).

Dann greife ich über eine Konvertierung mit XPath zu:
Delphi-Quellcode:
(XML.DOMDocument as IDOMNodeSelect).selectNode(XPath).childNodes[0].nodeValue := FieldValue;


Dabei gibt es zwei Probleme:
- es gibt keine Eigenschaft ".Text"
- es darf kein "Leerstring" als Text gespeichert sein, dann gibt es einen Zugriffsfehler
- es gibt keine ParentNodes etc

Was ist die beste Lösung, die diese Probleme vermeidet? IXMLDOMDocument?
Ich möchte XPath und Leertexte nutzen und möglichst in den Knoten "navigieren".

Die Datei muss nur zum Speichern und Laden meiner Daten dienen, externe Konventionen spielen für mich keine Rolle.

stahli 11. Aug 2010 21:05

AW: MSXML-Parser, aber welcher?
 
Ich beschäftige mich jetzt schon ein paar Tage mit XML-Parsern aber das ist schon etwas verwirrend ;-(

TXMLDocument ist recht einfach und komfortabel zu nutzen, bietet aber wohl auch einige Einschränkungen.
Daher habe ich es jetzt mit IXMLDOMDocument versucht.

Hier sind einmal die wesentlichen Punkte zu sehen:

Delphi-Quellcode:
uses
  msxml;
...
var
  xml: IXMLDOMDocument = nil;
  xmlNode, xmlRootNode: IXmlDomNode;
  xmlNodeList: IXmlDomNodeList;
...
  xml := coDOMDocument.Create; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
...
procedure CreateNewDatabase;
var
  xmlRoot: IXMLDomElement;
  xmlPI: IXMLDomProcessingInstruction;
const
  CodePage = 'UTF-8';
begin
  xml := CoDOMDocument.Create; // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//  xml.PreserveWhiteSpace := True; //??
  xmlPI := xml.CreateProcessingInstruction('xml', Format('version="1.0" encoding="%s"', [codepage]));
  xml.AppendChild(xmlPI);
  xmlRoot := xml.CreateElement('Wurzelknoten');
  xml.AppendChild(xmlRoot);
  xml.Save(DatabaseFileName);
end;
...
procedure OpenXml;
begin
  xml.Load(DatabaseFileName);
  xmlRootNode := xml.DocumentElement;
end;
...
function GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName: String): String;
var
  S: String;
begin
  S := '';
  if (NodeName <> '') and (FieldName <> '') then
  begin
    S := XPath + NodeName;
    if (IDName <> '') and (IDValue <> '') then
      S := S + '[@' + IDName + '="' + IDValue + '"]';
    S := S + '/' + FieldName;
  end;
  Result := S;
end;
...
function xmlRead (XPath, NodeName, IDName, IDValue, FieldName: String): String;
var
  Node: IXmlDomNode;
begin
  XPath := GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName);
  try
    Node := xmlRootNode.SelectSingleNode(XPath);
  except
    Node := nil;
  end;
  if Assigned(Node) then
    Result := Node.Text
  else
    Result := '';
end;
...
procedure xmlWrite(XPath, NodeName, IDName, IDValue, FieldName, FieldValue: String);
var
  Node: IXmlDomNode;
begin
  XPath := GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName);
  try
    Node := xmlRootNode.SelectSingleNode(XPath);
  except
    Node := nil;
  end;
  if Assigned(Node) then
    Node.Text := FieldValue
  else
    AutomatischerNeuerKnotenAnDer-XPath-Position!? // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
  RefreshXmlCtrlList;
end;
Meine Fragen:
1) Was ist an coDOMDocument60.Create besser? Und wo finde ich das???
2) Kann ich es irgendwie bewerkstelligen, dass beim Schreiben eines Textes (der Knoten ist mit XPath angegeben) AUTOMATISCH der bzw. die fehlenden Knoten erzeugt werden?
3) Gibt es alternativ Funktionen, die fehlende Knoten anhand eines XPath nachträglich generieren?

Das Lesen eines nicht existierenden Knotens liefert mit meiner xmlRead einfach '' zurück.
Jetzt suche ich eine Möglichkeit immer unproblematisch neue Inhalte in die XML zu schreiben (ähnlich wie bei einer Ini, da wird ja auch ggf. ein Eintrag neu erzeugt).

stahli 12. Aug 2010 22:03

AW: MSXML-Parser, aber welcher?
 
Ich werde wohl eine Kombination von IXMLNode und IDOMNode verwenden.

Über TXMLDocument kann man die komfortable Knotenverwaltung nutzen (allerdings ohne XPath).
Bestimmte Zugriffe auf existierende Knoten werde ich daher weiterhin über
Delphi-Quellcode:
(XML.DOMDocument as IDOMNodeSelect).selectNode(XPath)
lösen.

So kann ich beliebige Knoten im Dokument suchen oder über meine zwei Funktionen direkt auf bestimmte Knoten zugreifen.
Durch eine Überarbeitung können die Knoten nun auch "leer" sein, ohne dass es Probleme gibt:
Delphi-Quellcode:
function GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName: String): String;
var
  S: String;
begin
  S := '';
  if (NodeName <> '') and (FieldName <> '') then
  begin
    S := XPath + NodeName;
    if (IDName <> '') and (IDValue <> '') then
      S := S + '[@' + IDName + '="' + IDValue + '"]';
    S := S + '/' + FieldName;
  end;
  Result := S;
end;

function xmlRead (XPath, NodeName, IDName, IDValue, FieldName: String): String;
var
  N: IDOMNode;
begin
  Result := '';
  XPath := GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName);
  try
    N := (XML.DOMDocument as IDOMNodeSelect).selectNode(XPath);
    if Assigned(N) then
    begin
      if N.hasChildNodes then
      begin
        N := N.childNodes[0];
        if Assigned(N) then
        begin
          Result := N.nodeValue;
        end;
      end;
    end;
  except
    Beep;
  end;
end;

procedure xmlWrite(XPath, NodeName, IDName, IDValue, FieldName, FieldValue: String);
var
  N, NN: IDOMNode;
begin
  XPath := GetCompleteXPath(XPath, NodeName, IDName, IDValue, FieldName);
  try
    N := (XML.DOMDocument as IDOMNodeSelect).selectNode(XPath);
    if Assigned(N) then
    begin
      if N.hasChildNodes then
      begin
        N := N.childNodes[0];
        if Assigned(N) then
        begin
          N.nodeValue := FieldValue;
        end;
      end
      else
      begin
        NN := XML.DOMDocument.createTextNode(FieldName);
        NN.nodeValue := FieldValue;
        N.appendChild(NN);
      end;
    end;
  except
    Beep;
  end;
end;

Um Knoten hinzuzufügen nutze ich dann die komfortablen Möglichkeiten wie z.B. AddChild und XMLNode.Text unter TXMLDocument.

Ich denke, das sollte die beste Lösung sein.

stahli 15. Aug 2010 12:53

AW: MSXML-Parser, aber welcher?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Es geht noch etwas hin und her :?
Ich habe mich doch noch etwas näher mit den Expertenschnittstellen beschäftigt.
Grundsätzlich sind die nicht verkehrt...

Ich komme jedoch mit den Interfaces noch nicht klar. Und zwar möchte ich in meinen eigenen Komponenten Referenzen auf jeweils ein bestimmtes Knoteninterface verwalten.
Das sieht etwa so aus:

Delphi-Quellcode:
  TxmlCtrl = class(TComponent)
  private
    FXmlNode: IXmlNode;
...
    procedure SetXmlNode(const Value: IXmlNode);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
...
    property XmlNode  : IXmlNode read FXmlNode    write SetXmlNode;
  end;

procedure TxmlCtrl.SetXmlNode(const Value: IXmlNode);
begin
  if FXmlNode <> Value then
  begin
    FXmlNode := Value;
{
    if Assigned(XmlNode) then // nicht hilfreicher Test
      XmlNode._AddRef;
}
    InvalidateData;
  end;
end;
Im Projekt definiere ich dann die Wurzelschnittstelle und weise sie meiner Komponente zu.

Delphi-Quellcode:
var
  te: IXMLTournamentEvent; // im DataModule global definiert
...
  te := GetTournamentEvent(xml); // nach Projektstart, xml ist mein TXmlDocument
..
procedure TFormOlympic.Button1Click(Sender: TObject); // Test der Schnittstelle
var
  ix: IXmlNode;
begin
  Caption := te.Name;                                 // funktioniert: Caption = 'Test'
  ix := te;                                           // kein Promlem, zum Test mal eingerichtet
  Caption := Caption + ' !' + ix.NodeName;            // funktioniert: Caption = 'Test !TournamentEvent'
//  te._AddRef;                                       // (wirkungsloser Versuch)
  xmlEditTournamentEventName.xmlCtrl.XmlNode := te; // funktioniert grundsätzlich
                                                    // mit dem Knoten und Wert wird auch korrekt gearbeitet
                                                    // beim Programmende meckert jedoch FASTMM (siehe Anlage)
end;
Lasse ich den letzten Punkt weg, gibt es keine Probleme. Ich möchte aber meinen Komponenten jeweils einen bestimmten Knoten zuweisen.

Das xmlCtrl ist in diesem Fall eine Subkomponente meiner xmlEdit und greift direkt auf den Knotenwert zu.
Ich denke, dass beim Freigeben der xmlEdit bzw. deren xmlCtrl beim Projektende automatisch meine xml (TXmlDocument) freigegeben wird!?

Kann das sein?
Wie kann ich das verhindern und in meinen Komponenten ohne Nebenwirkungen Referenzen auf die enthaltenen IXmlNode speichern?
_AddRef hat mir in verschiedenen Versuchen noch nichts gebracht.
Auch ein
Delphi-Quellcode:
FXmlNode := nil
im
Delphi-Quellcode:
TxmlCtrl.Destroy
half nicht.

Danke für jede Hilfe!!

stahli 16. Aug 2010 09:51

AW: MSXML-Parser, aber welcher?
 
Das genannte Problem tritt nur auf, wenn ich den "Wurzelknoten" an meine Komponente übergebe. Andere Knoten machen dabei keine Probleme.
Ich habe zwar keine wirkliche Erklärung dafür, kann die Probleme über alternative Zugriffe aber leicht vermeiden.

(PS: Werde dann den Thread auch nicht mehr mit meinen Fragen zweckentfremden.)


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz