Delphi-PRAXiS
Seite 7 von 8   « Erste     567 8   

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 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.


Alle Zeitangaben in WEZ +2. Es ist jetzt 02:28 Uhr.
Seite 7 von 8   « Erste     567 8   

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