Delphi-PRAXiS
Seite 2 von 2     12

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Ideen für spezielle Stringbearbeitung (https://www.delphipraxis.net/117587-ideen-fuer-spezielle-stringbearbeitung.html)

toyoman 23. Jul 2008 16:15

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hallo,

hier eine kleine Starthilfe:

Delphi-Quellcode:
uses
  MSXML2;

function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin
  doc := CoDomDocument.Create;
  doc.async := False;
  Result := doc.loadXML(markup);
end;

procedure TDemoForm.TestButtonClick(Sender: TObject);
const
  MARKUP
    = '<Baskets totalNumber="3">'
    + '<Basket path="W:\briefkorb\test\" opened="false" isUserAssigned="true" />'
    + '<Basket path="W:\briefkorb\test1\" opened="false" isUserAssigned="true" />'
    + '<Basket path="H:\daten\Docuware\Ablage\" opened="false" isUserAssigned="false" />'
    + '</Baskets> '
    ;
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocument(doc, MARKUP) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
    n.nodeValue := ExtractFilePath(ParamStr(0));
    ShowMessage(doc.xml);
  end else ShowMessage(doc.parseError.reason);
end;
Statt MARKUP kann auch der Text aus der Datenbank eingesetzt werden.

Grüße vom marabu

danke, aber woher krieg ich MSXML2? Ich hab Delphi 2007. Scheint nicht Bestandteil zu sein?

marabu 23. Jul 2008 21:49

Re: Ideen für spezielle Stringbearbeitung
 
Hallo,

schau mal hier: XML DOM Importe

Freundliche Grüße

toyoman 24. Jul 2008 08:00

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hallo,

schau mal hier: XML DOM Importe

Freundliche Grüße

sorry muss nochmals blöd fragen, welche Version muss ich da nehmen? ich nehm an 6.0 die neuste?
Wenn ich die MSXML2_TLB.pas in mein Projekt einfüge scheint das dennoch nicht zu klappen...

mkinzler 24. Jul 2008 08:02

Re: Ideen für spezielle Stringbearbeitung
 
Nein es gibt mehrere verschiedene XML-Parser von Microsoft. Diese Unit wrappt MSXML2

toyoman 24. Jul 2008 08:37

Re: Ideen für spezielle Stringbearbeitung
 
Delphi-Quellcode:
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, XMLFile, XMLDOM, XMLIntf, msxmldom, XMLDoc, MSXML2_TLB;
Datei MSXML2_TLB ist im Projektverzeichnis...

kriege nun diesen Fehler:

[DCC Fehler] dw_xml.pas(32): E2003 Undefinierter Bezeichner: 'CoDomDocument'

marabu 24. Jul 2008 08:41

Re: Ideen für spezielle Stringbearbeitung
 
Moin,

öffne mal ein Befehlseingabefenster und schau dir mit DIR %WINDIR%\system32\MSXML?.DLL an, was die höchste Version deines installierten MSXML-Parsers ist. Und dann besorge dir wahlweise den Wrapper für MSXML4 (mit XDR) oder MSXML6 (ohne XDR).

Wahlweise kannst du dir den Wrapper selbst erstellen mit (D7): tlibimp -Fe- %windir%\system32\msxml4.dll

Und beachte, dass im generierten Wrapper je nach Version von TLIBIMP bestimmte Bezeichner umbenannt werden.

Freundliche Grüße

toyoman 24. Jul 2008 09:00

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Moin,

öffne mal ein Befehlseingabefenster und schau dir mit DIR %WINDIR%\system32\MSXML?.DLL an, was die höchste Version deines installierten MSXML-Parsers ist. Und dann besorge dir wahlweise den Wrapper für MSXML4 (mit XDR) oder MSXML6 (ohne XDR).

Wahlweise kannst du dir den Wrapper selbst erstellen mit (D7): tlibimp -Fe- %windir%\system32\msxml4.dll

Und beachte, dass im generierten Wrapper je nach Version von TLIBIMP bestimmte Bezeichner umbenannt werden.

Freundliche Grüße

ich hab Version 2,3,4 und 6 drauf. Die Wrapper Unit für Version 6 hab ich ja schon reinkopiert, dann müsst es doch eigentlich gehen oder?

marabu 24. Jul 2008 09:34

Re: Ideen für spezielle Stringbearbeitung
 
Hast du mal den Kommentar im Kopfteil von MSXML2_TLB.PAS durchgelesen?
Vielleicht wurde CoDomDocument umbenannt.

toyoman 24. Jul 2008 09:51

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hast du mal den Kommentar im Kopfteil von MSXML2_TLB.PAS durchgelesen?
Vielleicht wurde CoDomDocument umbenannt.

Von coDomDocument steht da nichts. Diverse andere ja...

Delphi-Quellcode:
//   Hinweis: Symbol 'DOMDocument' umbenannt zu 'msDOMDocument'
//   Hinweis: Symbol 'DOMDocument26' umbenannt zu 'msDOMDocument26'
//   Hinweis: Symbol 'DOMDocument30' umbenannt zu 'msDOMDocument30'
//   Hinweis: Symbol 'FreeThreadedDOMDocument' umbenannt zu 'msFreeThreadedDOMDocument'
//   Hinweis: Symbol 'FreeThreadedDOMDocument26' umbenannt zu 'msFreeThreadedDOMDocument26'
//   Hinweis: Symbol 'FreeThreadedDOMDocument30' umbenannt zu 'msFreeThreadedDOMDocument30'
//   Hinweis: Symbol 'XMLSchemaCache' umbenannt zu 'msXMLSchemaCache'
//   Hinweis: Symbol 'XMLSchemaCache26' umbenannt zu 'msXMLSchemaCache26'
//   Hinweis: Symbol 'XMLSchemaCache30' umbenannt zu 'msXMLSchemaCache30'
//   Hinweis: Symbol 'XSLTemplate' umbenannt zu 'msXSLTemplate'
//   Hinweis: Symbol 'XSLTemplate26' umbenannt zu 'msXSLTemplate26'
//   Hinweis: Symbol 'XSLTemplate30' umbenannt zu 'msXSLTemplate30'
//   Hinweis: Symbol 'XMLHTTP' umbenannt zu 'msXMLHTTP'
//   Hinweis: Symbol 'XMLHTTP26' umbenannt zu 'msXMLHTTP26'
//   Hinweis: Symbol 'XMLHTTP30' umbenannt zu 'msXMLHTTP30'
//   Hinweis: Symbol 'ServerXMLHTTP' umbenannt zu 'msServerXMLHTTP'
//   Hinweis: Symbol 'ServerXMLHTTP30' umbenannt zu 'msServerXMLHTTP30'
//   Hinweis: Symbol 'SAXXMLReader' umbenannt zu 'msSAXXMLReader'
//   Hinweis: Symbol 'SAXXMLReader30' umbenannt zu 'msSAXXMLReader30'
//   Hinweis: Symbol 'MXXMLWriter' umbenannt zu 'msMXXMLWriter'
//   Hinweis: Symbol 'MXXMLWriter30' umbenannt zu 'msMXXMLWriter30'
//   Hinweis: Symbol 'SAXAttributes' umbenannt zu 'msSAXAttributes'
//   Hinweis: Symbol 'SAXAttributes30' umbenannt zu 'msSAXAttributes30'
//   Hinweis: Parameter 'type' im IXMLDOMNode.nodeType geändert zu 'type_'
//   Hinweis: Element 'implementation' von 'IXMLDOMDocument' geändert zu 'implementation_'
//   Hinweis: Parameter 'type' im IXMLDOMDocument.createNode geändert zu 'type_'
//   Hinweis: Parameter 'var' im IXMLDOMSchemaCollection.add geändert zu 'var_'
//   Hinweis: Symbol 'type' umbenannt zu 'type_'
//   Hinweis: Parameter 'type' im ISchemaElement.type geändert zu 'type_'
//   Hinweis: Symbol 'type' umbenannt zu 'type_'
//   Hinweis: Parameter 'type' im ISchemaAttribute.type geändert zu 'type_'

marabu 24. Jul 2008 09:54

Re: Ideen für spezielle Stringbearbeitung
 
Wenn du genau liest, dann findest du heraus, dass du ComsDOMDocument verwenden musst. klick

toyoman 24. Jul 2008 10:16

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hallo,

hier eine kleine Starthilfe:

Delphi-Quellcode:
uses
  MSXML2;

function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin
  doc := CoDomDocument.Create;
  doc.async := False;
  Result := doc.loadXML(markup);
end;

procedure TDemoForm.TestButtonClick(Sender: TObject);
const
  MARKUP
    = '<Baskets totalNumber="3">'
    + '<Basket path="W:\briefkorb\test\" opened="false" isUserAssigned="true" />'
    + '<Basket path="W:\briefkorb\test1\" opened="false" isUserAssigned="true" />'
    + '<Basket path="H:\daten\Docuware\Ablage\" opened="false" isUserAssigned="false" />'
    + '</Baskets> '
    ;
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocument(doc, MARKUP) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
    n.nodeValue := ExtractFilePath(ParamStr(0));
    ShowMessage(doc.xml);
  end else ShowMessage(doc.parseError.reason);
end;
Statt MARKUP kann auch der Text aus der Datenbank eingesetzt werden.

Grüße vom marabu

Hallo marabu

in Bezug auf deinen Beispielcode: kannst du mir noch erklären was das mit dem MARKUP und XPATH auf sich hat?
ist das der Suchstring oder für was brauchts das?
Wenn ich jetzt deinen Beispielcode ausführe erhalte ich nämlich nur die Meldung:
Ein XML-Dokument muss ein Element der obersten Ebene enthalten.

Ich blick immer noch nicht durch.

toyoman 24. Jul 2008 10:16

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Wenn du genau liest, dann findest du heraus, dass du ComsDOMDocument verwenden musst. klick

ok hab ich jetzt gefunden...

marabu 24. Jul 2008 11:09

Re: Ideen für spezielle Stringbearbeitung
 
MARKUP ist bei mir einfach eine Konstante, bei dir der String mit dem DocuWare-XML, den du aus deiner Datenbank gelesen hast. Wenn mit dem XML-String irgendwas nicht stimmt, dann erhältst du eine Fehlermeldung, wie du ja gemerkt hast. Schau dir den XML-String mal genau an oder stelle den Text hier ein.

XPATH ist eine Spezifikation zur Addressierung einzelner DOM-Objekte. Der Zugriff über einen XPath-Ausdruck erspart dir umständliches Navigieren per Code.

toyoman 24. Jul 2008 11:28

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
MARKUP ist bei mir einfach eine Konstante, bei dir der String mit dem DocuWare-XML, den du aus deiner Datenbank gelesen hast. Wenn mit dem XML-String irgendwas nicht stimmt, dann erhältst du eine Fehlermeldung, wie du ja gemerkt hast. Schau dir den XML-String mal genau an oder stelle den Text hier ein.

XPATH ist eine Spezifikation zur Addressierung einzelner DOM-Objekte. Der Zugriff über einen XPath-Ausdruck erspart dir umständliches Navigieren per Code.

Den XML String hab ich hier schon eingefügt (eine Seite zurück im Thread).
hab jetzt den Markup zu einer Variable gemacht und meinen XML String zugewiesen. Dadurch erhalte ich nun die sehr aussagekräftige Meldung: "An dieser Stelle sind keine Leerzeichen zugelassen."

Ich freue mich :)

marabu 24. Jul 2008 11:56

Re: Ideen für spezielle Stringbearbeitung
 
Dein XML-Dokument aus Beitrag #37 wird von meinem Beispiel-Code aus Beitrag #39 problemlos verarbeitet. Ich habe dein Dokument über die Zwischenablage in eine Datei kopiert und von dort zur Laufzeit in ein Memo geladen. Ich übergebe dann Memo.Text anstelle von MARKUP.

toyoman 25. Jul 2008 08:03

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Dein XML-Dokument aus Beitrag #37 wird von meinem Beispiel-Code aus Beitrag #39 problemlos verarbeitet. Ich habe dein Dokument über die Zwischenablage in eine Datei kopiert und von dort zur Laufzeit in ein Memo geladen. Ich übergebe dann Memo.Text anstelle von MARKUP.

Ok, meine Prozedur schaut nun so aus:

Delphi-Quellcode:
procedure Tfrmxml.Button1Click(Sender: TObject);
function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin
  doc := ComsDOMDocument.Create;
  doc.async := False;
  Result := doc.loadXML(markup);
end;
const
{  MARKUP
    = ''
    + ''
    + ''
    + ''
    + ' '
    ;}
  XPATH = '//Basket[%d]/@path';
var
  anzahl: integer;
  i: integer;

  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
  MARKUP : string;


begin
  MARKUP := memo1.text;
  if CreateDocument(doc, MARKUP) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
    n.nodeValue := ExtractFilePath(ParamStr(0));
    ShowMessage(doc.xml);
  end else ShowMessage(doc.parseError.reason);


{   XMLDocument1.LoadFromFile(getpath+'test.xml');
   if xmldocument1.DocumentElement.NodeName='Baskets' then
   begin
       anzahl:=XMLDocument1.DocumentElement.Attributes['totalNumber'];
       for i := 0 to anzahl-1 do
       begin
         showmessage(XMLDocument1.DocumentElement.ChildNodes.Nodes[i].Attributes['path'])
       end;
   end;}

end;
Und dabei krieg ich die erwähnte Meldung (im memo1.text ist genau der XML String drin welcher in Beitrag #37 drin steht... )

marabu 25. Jul 2008 09:26

Re: Ideen für spezielle Stringbearbeitung
 
Moin,

kennst du keine Möglichkeiten einen Fehler einzugrenzen?

Versuche es mal so:

Delphi-Quellcode:
function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin
  doc := ComsDOMDocument.Create;
  doc.async := False;
  Result := doc.loadXML(markup);
end;

procedure ShowParseError(pe: IXMLDOMParseError);
const
  FMT = 'line %d, linepos %d'#13'%s'#13#13'%s';
begin
  with pe do
    ShowMessage(Format(FMT, [line, linepos, reason, Copy(srctext, 1, linepos)]));
end;

procedure Tfrmxml.Button1Click(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocument(doc, Memo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Freundliche Grüße

toyoman 25. Jul 2008 09:33

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Moin,

kennst du keine Möglichkeiten einen Fehler einzugrenzen?

Versuche es mal so:

Delphi-Quellcode:
function CreateDocument(var doc: IXMLDOMDocument2; const markup: string): Boolean;
begin
  doc := ComsDOMDocument.Create;
  doc.async := False;
  Result := doc.loadXML(markup);
end;

procedure ShowParseError(pe: IXMLDOMParseError);
const
  FMT = 'line %d, linepos %d'#13'%s'#13#13'%s';
begin
  with pe do
    ShowMessage(Format(FMT, [line, linepos, reason, Copy(srctext, 1, linepos)]));
end;

procedure Tfrmxml.Button1Click(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocument(doc, Memo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Freundliche Grüße

In diesem Fall nicht, da ich mich damit nicht auskenne. Keine Ahnung wo ich da suchen soll.
Sonst wär ich wohl nicht hier im Forum drin...

toyoman 25. Jul 2008 09:42

Re: Ideen für spezielle Stringbearbeitung
 
line 5, linepos 70
An dieser Stelle sind keine Leerzeichen zugelassen.

oldIniSettingsForDW="[bibl_00995018.184_RESULT]#xD;#xA;COLFIXED=0#

hab den String jetzt extra hier nochmal von Hand eingegeben und ich kann wirklich kein Leerzeichen entdecken.

marabu 25. Jul 2008 10:10

Re: Ideen für spezielle Stringbearbeitung
 
Du interpretierst die übersetzte Fehlermeldung falsch - mit Leerzeichen ist white space gemeint und dazu zählen auch die kodierten Zeilenumbrüche.

Dein Fehler tritt bei mir nicht auf, weil ich mit MSXML4 getestet habe, du aber wohl MSXML6 benutzt.

toyoman 25. Jul 2008 10:20

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Du interpretierst die übersetzte Fehlermeldung falsch - mit Leerzeichen ist white space gemeint und dazu zählen auch die kodierten Zeilenumbrüche.

Dein Fehler tritt bei mir nicht auf, weil ich mit MSXML4 getestet habe, du aber wohl MSXML6 benutzt.

um MSXML4 zu nutzen kopier ich einfach die Unit MSXML2_TLB.pas vom Zip XML.v4.0.zip ins Projektverzeichnis rein oder?

hab ich mal so gemacht und bekomm wieder die selbe Meldung.

marabu 25. Jul 2008 10:28

Re: Ideen für spezielle Stringbearbeitung
 
So kommen wir nicht weiter.

Mach bitte eine kleine Demo fertig, erstelle ein ZIP-Archiv der Quellen und hänge das hier rein. Ich schaue mir das dann an.

toyoman 25. Jul 2008 11:02

Re: Ideen für spezielle Stringbearbeitung
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von marabu
So kommen wir nicht weiter.

Mach bitte eine kleine Demo fertig, erstelle ein ZIP-Archiv der Quellen und hänge das hier rein. Ich schaue mir das dann an.

Hier das Beispielprojekt!

marabu 26. Jul 2008 17:07

Re: Ideen für spezielle Stringbearbeitung
 
Hallo,

versuche es mal so:

Delphi-Quellcode:
function CreateDocumentFromUrl(var doc: IXMLDOMDocument2; const url: string): Boolean;
begin
  doc := ComsDOMDocument.Create;
  doc.async := False;
  Result := doc.load(url);
end;

{
  ...
}

procedure Tfrmxml.Button1Click(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocumentFromUrl(doc, 'beispiel.xml') then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Weil du beim Memo die property Wrap auf True gesetzt hast, wird der Text umgebrochen - leider aber nach Regeln, die der XML-Parser nicht mag.

Hättest du Wrap auf False gesetzt (default), dann wäre dir der zwangsweise Umbruch nach 1024 Zeichen pro Zeile (editor limitation) zum Verhängnis geworden, da wahrscheinlich wieder an einer für den XML-Parser nicht akzeptablen Stelle umgebrochen worden wäre.

Entweder du liest das Dokument erst zur Laufzeit in dein Memo ein, oder - wenn du das Memo nicht zur Visualisierung benötigst - du lässt das XML-Dokument gleich vom Parser lesen, wie ich es mit CreateDocumentFromUrl() zeige.

Freundliche Grüße

toyoman 4. Aug 2008 11:40

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hallo,

versuche es mal so:

Delphi-Quellcode:
function CreateDocumentFromUrl(var doc: IXMLDOMDocument2; const url: string): Boolean;
begin
  doc := ComsDOMDocument.Create;
  doc.async := False;
  Result := doc.load(url);
end;

{
  ...
}

procedure Tfrmxml.Button1Click(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocumentFromUrl(doc, 'beispiel.xml') then
  begin
    n := doc.selectSingleNode(Format(XPATH, [1]));
    ShowMessage(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Weil du beim Memo die property Wrap auf True gesetzt hast, wird der Text umgebrochen - leider aber nach Regeln, die der XML-Parser nicht mag.

Hättest du Wrap auf False gesetzt (default), dann wäre dir der zwangsweise Umbruch nach 1024 Zeichen pro Zeile (editor limitation) zum Verhängnis geworden, da wahrscheinlich wieder an einer für den XML-Parser nicht akzeptablen Stelle umgebrochen worden wäre.

Entweder du liest das Dokument erst zur Laufzeit in dein Memo ein, oder - wenn du das Memo nicht zur Visualisierung benötigst - du lässt das XML-Dokument gleich vom Parser lesen, wie ich es mit CreateDocumentFromUrl() zeige.

Freundliche Grüße

juhu zurück aus den Ferien und schon das erste Erfolgserlebnis dank marabu :)
Ich kann jetzt zumindest schon mal den Pfad einlesen. Jetzt muss ich noch gucken wie ich den modifiziere bzw. neuanlege..... (?)

dankevielmals für die geduldige hilfe bis dahin :)

toyoman 5. Aug 2008 11:26

Re: Ideen für spezielle Stringbearbeitung
 
ich hab das ganze jetzt so gemacht:

Delphi-Quellcode:
procedure Tfrmxml.btnanzClick(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
  XANZAHL = '//Baskets[%d]/@totalNumber';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  // Anzahl Briefkörbe auslesen
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XANZAHL, [1]));
    edanzahl.text:=(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
  // Briefkorb Pfad auslesen
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)]));
    edpfad.text:=(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);


{  if CreateDocumentFromUrl(doc, 'beispiel.xml') then
  begin
    n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)]));
    edpfad.text:=(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);}
end;
dbmemo1 ist eine dbmemo welche ich direkt aus der db abfülle. soweit so gut. aber wo kann ich den kosmischen XML code //baskets[%d] usw. lernen? ich möchte nämlich jetzt im zweiten schritt den wert: Baskets totalNumber auslesen. So wie ich es oben gemacht habe scheint es nicht zu stimmen, ich krieg eine Zugriffsverletzung. was mach ich falsch?

bin weitergekommen. Und zwar hab ich das %d weggelassen bei der Definition von XANZAHL. Ich versteh zwar nicht warum (was bedeutet dieses %d???).

kannst du mir noch sagen wie ich jetzt den mutierten Wert aus edpfad.text wieder in den XML String speichere? Ich dachte evl. mit: n.nodeValue:=edpfad.text? Aber wie krieg ich den geänderten Node dann in den XML rein?

marabu 5. Aug 2008 13:56

Re: Ideen für spezielle Stringbearbeitung
 
Hallo,

du solltest den XML Code nur einmal laden:

Delphi-Quellcode:
procedure Tfrmxml.btnanzClick(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
  XANZAHL = '//Baskets[%d]/@totalNumber';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
begin
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    // Anzahl Briefkörbe auslesen
    n := doc.selectSingleNode(Format(XANZAHL, [1]));
    edanzahl.text:=(VarToStr(n.nodeValue));
    // Briefkorb Pfad auslesen
    n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)]));
    edpfad.text:=(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Das Verändern des Pfades hatte ich dir bereits in Beitrag #39 gezeigt. An den aktuellen XML Code gelangst du über doc.xml, was ich dir im gleichen Beitrag auch gezeigt habe. %d ist ein sogenannter format specifier und du findest diese im Help Topic "Format-Strings" beschrieben. Nach Ersetzung der Platzhalter durch die Funktion Format() erhältst du einen sogenannten XPATH-Ausdruck. XPATH ist eine W3-Spezifikation zur genauen Lokalisierung von Objekten in einem XML Document Object Model (XML DOM).

Freundliche Grüße

toyoman 5. Aug 2008 14:39

Re: Ideen für spezielle Stringbearbeitung
 
du hast Recht marabu. Sorry hab mir das nochmals vor Augen geführt und umgesetzt:

Definition der SQL Statements:

Delphi-Quellcode:
unit mySQLstatements;

interface

uses Windows, myGlobals, nsa_spezial;

const
  sql_read_benutzer:     string = 'SELECT iid, domain, user_account from DWWinUserID';
  sql_read_briefkorb:    string = 'SELECT name, password, guid, settings, active from DWUser where name = $benutzername';
  sql_update_xml:        string = 'UPDATE DWUser set settings = $xml where name = $benutzername';
Prozedur:

Delphi-Quellcode:
procedure Tfrmxml.edmutClick(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
  XANZAHL = '//Baskets/@totalNumber';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
  sqltext:string;
  s:string;
begin
  s:=chr(39); // Hochkomma
  // Briefkorb Pfad speichern
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)-1]));
    n.nodeValue:=(edpfad.text);
    sqltext:=stringreplace(sql_update_xml,'$benutzername',s+edbenutzername.text+s,[rfIgnoreCase]);
    sqltext:=stringreplace(sqltext,'$xml',s+doc.xml+s,[rfIgnoreCase]);
    datamodule2005.ADOQuery3.SQL.Text:=sqltext;
    datamodule2005.ADOQuery3.ExecSQL;
    showmessage(sqltext);
    //edpfad.text:=(VarToStr(n.nodeValue));
  end else ShowParseError(doc.parseError);
end;
Parameter object is improperly defined. Inconsistent or incomplete information was provided.

Kann nix mit der Meldung anfangen. Hab ich was vergessen?

marabu 5. Aug 2008 18:17

Re: Ideen für spezielle Stringbearbeitung
 
Hallo,

du hast vergessen die Stelle zu bezeichnen, an der der Fehler auftritt.

Außerdem scheint es so, als ob du versuchst ein feature der ADO-Komponenten nachzubilden: Parameter. Statt des Dollarzeichens verwendest du dann einen Doppelpunkt:

Delphi-Quellcode:
const
  SQL_SEL_ACCTS
    = 'SELECT iid, domain, user_account '
    + 'FROM DWWinUserID '
    ;
  SQL_SEL_USER
    = 'SELECT name, password, guid, settings, active '
    + 'FROM DWUser WHERE name = :benutzername '
    ;
  SQL_UPD
    = 'UPDATE DWUser SET settings = :xml '
    + 'WHERE name = :benutzername '
    ;
Die durch den Doppelpunkt markierten Parameter werden dir in der Eigenschaft Params einer DataSet-Komponente zur Manipulation angeboten. Ein Beispiel von vielen zum Umgang mit Params findest du z.B. hier: klick

In deinem konkreten Fall könnte der XML Parser direkt aus einem BlobStream lesen und dort auch wieder hin schreiben. Dabei könnten dir die Funktionen LoadDocument() und SaveDocument() helfen.

BTW: "name" ist kein besonders gut gewählter Name für eine Spalte.

Freundliche Grüße

toyoman 5. Aug 2008 22:47

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Hallo,

du hast vergessen die Stelle zu bezeichnen, an der der Fehler auftritt.

Außerdem scheint es so, als ob du versuchst ein feature der ADO-Komponenten nachzubilden: Parameter. Statt des Dollarzeichens verwendest du dann einen Doppelpunkt:

Delphi-Quellcode:
const
  SQL_SEL_ACCTS
    = 'SELECT iid, domain, user_account '
    + 'FROM DWWinUserID '
    ;
  SQL_SEL_USER
    = 'SELECT name, password, guid, settings, active '
    + 'FROM DWUser WHERE name = :benutzername '
    ;
  SQL_UPD
    = 'UPDATE DWUser SET settings = :xml '
    + 'WHERE name = :benutzername '
    ;
Die durch den Doppelpunkt markierten Parameter werden dir in der Eigenschaft Params einer DataSet-Komponente zur Manipulation angeboten. Ein Beispiel von vielen zum Umgang mit Params findest du z.B. hier: klick

In deinem konkreten Fall könnte der XML Parser direkt aus einem BlobStream lesen und dort auch wieder hin schreiben. Dabei könnten dir die Funktionen LoadDocument() und SaveDocument() helfen.

BTW: "name" ist kein besonders gut gewählter Name für eine Spalte.

Freundliche Grüße


Hey

Der Fehler tritt im Ausführungsmoment auf (ExecSQL). Ich befürchte der XML String ist zu lang um den in einen SQL Update einzubetten. Ist das möglich?
Wie ich ADO Parameter verwende weiss ich und verwend ich auch ab und zu. Aber nicht in diesem Fall wo es sich um ein einfaches Projekt handelt. So ist diese Lösung für mich die einfachere und naheliegendere.
Den Spaltennamen "name" ist nicht nach meinem Wunsch so getauft worden. Dies hat die Herstellerfirma der Software so gemacht und ist somit nicht in meinem Einflussbereich. Ich muss damit arbeiten obs schlau ist oder nicht.

toyoman 6. Aug 2008 08:26

Re: Ideen für spezielle Stringbearbeitung
 
Erfolgserlebnis:

Delphi-Quellcode:
procedure Tfrmxml.btnmutClick(Sender: TObject);
const
  XPATH = '//Basket[%d]/@path';
  XANZAHL = '//Baskets/@totalNumber';
var
  doc: IXMLDOMDocument2;
  n: IXMLDOMNode;
  sqltext:string;
  s:string;
begin
  s:=chr(39); // Hochkomma
  // Briefkorb Pfad speichern
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    n := doc.selectSingleNode(Format(XPATH, [strtoint(ednummer.text)-1]));
    n.nodeValue:=(edpfad.text);
//    sqltext:=stringreplace(sql_update_xml,'$benutzername',s+edbenutzername.text+s,[rfIgnoreCase]);
//    sqltext:=stringreplace(sqltext,'$xml',s+doc.xml+s,[rfIgnoreCase]);
    datamodule2005.ADOQuery3.SQL.Text:=sql_update_xml;
    datamodule2005.ADOQuery3.Parameters.ParamByName('xml').Value:=doc.xml;
    datamodule2005.ADOQuery3.Parameters.ParamByName('benutzername').Value:=edbenutzername.text;
    showmessage(datamodule2005.ADOQuery3.SQL.Text);
    datamodule2005.ADOQuery3.ExecSQL;
  end else ShowParseError(doc.parseError);
end;
Danke für den Tipp marabu. Mithilfe von Parametern scheint sich das Problem in Luft aufgelöst zu haben. Ist mir zwar nicht klar warum, aber ok.
Was ich noch ändern musste: doc.xml verwenden und nicht in Hochkomma in die DB setzen.

toyoman 6. Aug 2008 11:43

Re: Ideen für spezielle Stringbearbeitung
 
Bei mir ist jetzt noch die Frage aufgetaucht:
Wenn ein Benutzer keinen Basket im XML definiert hat (totalNumber=0). Wie kann ich diesen dann eintragen/speichern/eröffnen?
Hast du da ein Beispiel?

Das wäre noch das Tüpfli auf dem i - wie wir in der CH sagen :)

marabu 6. Aug 2008 14:19

Re: Ideen für spezielle Stringbearbeitung
 
Sali,

luegsch emal:

Delphi-Quellcode:
procedure AddBasket(doc: IXMLDOMDocument2; const path, opened, isUserAssigned: string);
const
  xpBaskets = '//Baskets';
  tagBasket = 'Basket';
  atPath = 'path';
  atOpened = 'opened';
  atIsUserAssigned = 'isUserAssigned';
var
  e: IXMLDOMElement;
begin
  e := doc.selectSingleNode(xpBaskets) as IXMLDOMElement;
  if Assigned(e) then
    with e.appendChild(doc.createElement(tagBasket))
    as IXMLDOMElement do
    begin
      setAttribute(atPath, path);
      setAttribute(atOpened, opened);
      setAttribute(atIsUserAssigned, isUserAssigned);
    end;
end;
Tschüss

toyoman 6. Aug 2008 16:30

Re: Ideen für spezielle Stringbearbeitung
 
Zitat:

Zitat von marabu
Sali,

luegsch emal:

Delphi-Quellcode:
procedure AddBasket(doc: IXMLDOMDocument2; const path, opened, isUserAssigned: string);
const
  xpBaskets = '//Baskets';
  tagBasket = 'Basket';
  atPath = 'path';
  atOpened = 'opened';
  atIsUserAssigned = 'isUserAssigned';
var
  e: IXMLDOMElement;
begin
  e := doc.selectSingleNode(xpBaskets) as IXMLDOMElement;
  if Assigned(e) then
    with e.appendChild(doc.createElement(tagBasket))
    as IXMLDOMElement do
    begin
      setAttribute(atPath, path);
      setAttribute(atOpened, opened);
      setAttribute(atIsUserAssigned, isUserAssigned);
    end;
end;
Tschüss

gruäzi

scheinbar hab ich wieder was missverstanden oder falsch gemacht. denn es passiert gar nix. habe es folgendermassen in einer prozedur verpackt:

Delphi-Quellcode:
procedure Tfrmxml.btnneubClick(Sender: TObject);
var
  doc: IXMLDOMDocument2;
begin
  if CreateDocument(doc, dbMemo1.Text) then
  begin
    AddBasket(doc,edpfad.text,'true','true');
    datamodule2005.ADOQuery3.SQL.Text:=sql_update_xml;
    datamodule2005.ADOQuery3.Parameters.ParamByName('xml').Value:=doc.xml;
    datamodule2005.ADOQuery3.Parameters.ParamByName('benutzername').Value:=edbenutzername.text;
    datamodule2005.ADOQuery3.ExecSQL;
    btnneu.click; // Neu!
  end else ShowParseError(doc.parseError);
end;
wie gesagt, wird leider nichts gespeichert. wahrscheinlich wieder eine kleine sache??

toyoman 6. Aug 2008 16:42

Re: Ideen für spezielle Stringbearbeitung
 
XML to String.
Gibts sowas eigentlich? Bzw. doc (IXMLDOMDocument2) to String.

doc.xml...
mensch ist wohl schon spät. sorry


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:30 Uhr.
Seite 2 von 2     12

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