Probleme mit einer Xml-Datei...

Alles rund um die Programmierung mit Qt
Antworten
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Probleme mit einer Xml-Datei...

Beitrag von reinki0013 »

Hallo zusammen,

also nachdem ich wirklich sehr lange auf der forums-suche unterwegs war muss ich leider einen neuen thread eröffnen, da es einfach nichts passendes gibt...

kurze erklärung was ich eigentlich will :roll: :

immer ans ende einer xml-datei schreiben und dabei überprüfen ob die einträge schon vorhanden sind.


folgende probleme habe ich aktuell:

ans ende der datei schreibe ich mit file.open(QIODevice::Append).
das funzt soweit, allerdings schreibt er immer die erste zeile

Code: Alles auswählen

"<?xml version="1.0" encoding="UTF-8"?>"
desweitern würde ich gerne wissen, ob es eine funktion gibt mit der ich überprüfen kann ob der eintrag schon vorhanden ist, oder ob ich das wieder mit einem QXmlStreamReader öffnen muss...

hier der code der funktion:

Code: Alles auswählen

  
  if(file.open(QIODevice::Append))
  {
    QXmlStreamWriter xml(&file);
    xml.setAutoFormatting(true);

    xml.writeStartDocument();
    xml.writeStartElement(listComboBox[0]);

    for(int i = 1; i < listComboBox.count(); i++)
      xml.writeTextElement(listLabel[i], listComboBox[i]);

    xml.writeEndElement();
    xml.writeEndDocument();
  }
wäre super wenn ihr mir weiterhelfen könnt...
bin für sämtliche ratschläge und tipps sehr dankbar...

lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Du kannst ein XML-Dokument nicht einfach per Append auf Filebene erweitern.
Ein XML-File hat GENAU EIN Element auf oberster Ebene. Dieses wird beim Schreiben wieder geschlossen. Wenn du jetzt deine neuen Daten einfach hinten anhängst, bekommst du ein zweites oberstes Element, was kein gültiges XML mehr ist, und ich bezweifle, dass ein XML-Parser damit noch ordentlich zurecht kommt, das wird wohl in Richtung undefiniertes Verhalten gehen ;)

Und wenn du die Doku liest, weißt du, dass QXmlStreamWriter::writeStartDocument() jene Zeile mit der XML-Version, Encoding usw. schreibt. Wenn du die Zeile nicht haben willst, musst du das weglassen :P
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

franzf hat geschrieben:Du kannst ein XML-Dokument nicht einfach per Append auf Filebene erweitern.
Ein XML-File hat GENAU EIN Element auf oberster Ebene. Dieses wird beim Schreiben wieder geschlossen. Wenn du jetzt deine neuen Daten einfach hinten anhängst, bekommst du ein zweites oberstes Element, was kein gültiges XML mehr ist, und ich bezweifle, dass ein XML-Parser damit noch ordentlich zurecht kommt, das wird wohl in Richtung undefiniertes Verhalten gehen ;)

Und wenn du die Doku liest, weißt du, dass QXmlStreamWriter::writeStartDocument() jene Zeile mit der XML-Version, Encoding usw. schreibt. Wenn du die Zeile nicht haben willst, musst du das weglassen :P
also wenn ich die zeile QXmlStreamWriter::writeStartDocument() weglasse, dann kann ich es ja mit QXmlStreamReader nicht mehr aufmachen, oder ist das egal??

wie kann ich dann die datei auf vorhandene einträge durchsuchen?
manuell oder gibt es da was fertiges?

lg
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Schau dir mal die Doku zu QDomDocument an.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

reinki0013 hat geschrieben:wie kann ich dann die datei auf vorhandene einträge durchsuchen?
manuell oder gibt es da was fertiges?
Manuell: indem du dir einen XML-Parser (oder eben eine auf dein Problem abgespckte Version) schreibst. Ist unsinnig, weil es dafür schon fertige Sachen gibt ;)
Am einfachsten dürfte es sein, das XML in ein QDomDocument einzulesen, nach deinem Eintrag zu suchen und da den Wert zu setzen. Oder eben einen neuen Eintrag hinzuzufügen. Ist alles erledigt, speicherst du das QDomDocument wieder auf die Festplatte.

Aus deinem Codestück würde ich aber sagen XML ist dafür total übertrieben. Du hast ja gar keine Tiefe, alle Einträge liegen auf einer Ebene.
Ich würde ganz einfach nur ein simples Textfile nehmen, und dort Einträge "key=value" setzen, das ist leicht zu lesen, leicht zu parsen, und dir kommt keine Spezifikation in die Quere, so dass du auch mit Append ans Ende der Datei schreiben kannst.
Oder eben gleich mit QSettings arbeiten.
also wenn ich die zeile QXmlStreamWriter::writeStartDocument() weglasse, dann kann ich es ja mit QXmlStreamReader nicht mehr aufmachen, oder ist das egal??
Das ist nicht mein Punkt, wie gesagt kannst du auch gar nicht ans Ende schreiben, ohne die XML-Spezifikation zu verletzen!
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

guten morgen,

also besten dank vorerst mal...

bezüglich der tiefe der xml-datei...
meine struktur sollte folgendermaßen aussehen:

Code: Alles auswählen

<System>
  <System Nr. 1>
      <Text 1>
      <Text 2>
      <Text 3>
  </System Nr. 1>
  <System Nr. 2>
      <Text 1>
      <Text 2>
      <Text 3>
  </System Nr. 2>
</System>
so würde ich das gerne machen...
danach möchte ich natürlich gerne die datei überprüfen ob systeme schon enthalten sind und wenn ja überschreiben.
wenn systeme nicht vorhanden, dann ans ende der datei schreiben...

was meint ihr dazu?
wie kann ich das jetzt am besten umsetzen?

danke,
lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

reinki0013 hat geschrieben:bezüglich der tiefe der xml-datei...
meine struktur sollte folgendermaßen aussehen:

Code: Alles auswählen

<System>
  <System Nr. 1>
      <Text 1>
      <Text 2>
      <Text 3>
  </System Nr. 1>
  <System Nr. 2>
      <Text 1>
      <Text 2>
      <Text 3>
  </System Nr. 2>
</System>
Verwende QSettings mit INI-Format, mehr brauchst du nicht. Außer in deinem Pflichtenheft steht "wir wollen XML!" oder du willst mal mit Xml rumspielen. Würde ich dann aber nicht in einem großen Projekt machen sondern in einem kleinen Test-Projekt.
BTW. ist das immer noch total unsinnig, weil du lauter leere XML-Nodes hast. Sinniger wäre wenn dann

Code: Alles auswählen

<System>
  <SubSys Nummer="1">
      <Element>Text 1</Element>
      <Element>Text 2</Element>
      <Element>Text 3</Element>
  </System Nr. 1>
[usw]
</System>
so würde ich das gerne machen...
danach möchte ich natürlich gerne die datei überprüfen ob systeme schon enthalten sind und wenn ja überschreiben.
wenn systeme nicht vorhanden, dann ans ende der datei schreiben...

was meint ihr dazu?
wie kann ich das jetzt am besten umsetzen?
Leseresistent?
Wenn es gültiges XML werden soll KANNST DU NICHT ans Ende der Datei schreiben!
Die Lösung wurde auch schon mehrfach gesagt: QDomDocument + Konsorten.
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Noch ne Anmerkung:

Text Elemente sollte man wirklich nur fuer längeren Fliesstext bzw unspezifizierte Textbloecke verwenden, ansonsten sind Attribute dann wohl das bessere Mittel. find ich auch angenehmer zu parsen, weil die der parser ned zerhaeckseln kann ^^

Code: Alles auswählen

<Systems> 
    <System Name="Name1" Nummer="1" \> 
    <System Name="Name2" Nummer="2" \> 
</Systems> 
Ciao ...
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

guten morgen,

also der ansatz mit QSettings ist super, an das habe ich gar nicht gedacht...

mit der funktion .beginGroup und .endGroup kann ich das erreichen was ich will...es muss ja nicht zwangsweise xml-sein :lol:

ich habe jetzt noch eine frage bezüglich ".beginGroup()":
wenn ich da jetzt einen QString reinschreibe (z.b. System 1.0) habe ich das problem das ihm das leerzeichen nicht passt...

vorher "System 1.0"
nachher "System%201.0"

wie kann ich das verhindern??

lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

reinki0013 hat geschrieben:wenn ich da jetzt einen QString reinschreibe (z.b. System 1.0) habe ich das problem das ihm das leerzeichen nicht passt...

vorher "System 1.0"
nachher "System%201.0"
Das wird nur von QSettings geschrieben, wenn du es wieder liest ist das %20 wieder ein Leerzeichen. Ob du das irgendwie verhindern kannst weiß ich nicht. Ambesten einfach die groups und keys ohne Leerzeichen schreiben ;)
"System 1.0" -> System_1.0
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

supa, danke...

jetzt muss ich nochmal lästig sein :oops:

und zwar schreibe ich jetzt tadellos in die groups, funzt perfekt...
jetzt habe ich eine StringList mit versch. Einträgen und möchte die Groups durchsuchen wo diese Einträge vorhanden sind und die Group zurückgeben...

[System_1.0]
Eigenschaften=Test1
Eigenschaften=Test2

[System_2.0]
Eigenschaften=Test2

usw.

ich möchte jetzt z.b. suchen Test1 und Test2...

gibt`s da dann eine funktion die mir jetzt z.b. System_1.0 zurückgibt?

mit QSettings::childGroups() bekomme ich nur die Gruppen zurück
mit QSettings::AllKeys() bekomme ich alle Key`s zurück

hoffe ihr versteht mich

:roll:

lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Das da

Code: Alles auswählen

[System_1.0]
Eigenschaften=Test1
Eigenschaften=Test2 
geht sowieso nicht ;)
Ein Key ist EINDEUTIG!
Wenn du eine QStringList speichern willst, dann tu das auch.

Code: Alles auswählen

QStringList lst;
lst << "Hallo" << "Dies" << "Ist" << "Eine" << "StringList";
settings.setValue("System_1.0/Eigenschaften", lst);
Dabei kommt in der Datei dann sowas raus:

Code: Alles auswählen

[System_1.0]
Eigenschaften=Hallo, Dies, Ist, Eine, StringList
Dann kannst du durch alle Keys (QSettings::allKeys()) durchwandern und die "Eigenschaften"->toStringList() nach dem "Test2" befragen.
Warum willst du denn eigentlich in den Settings selber suchen? Ich dachte, du hast da eh schon ComboBoxen rumliegen, frag doch die ;)
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

hi,

also die comboboxen dienen als auswahl feld nach was ich eigentlich suchen will...

das mit der QStringList wusste ich nicht, dass ich das so machen kann, dachte nur QStrings wären möglich, toll danke!!!

wenn ich jetzt mit

Code: Alles auswählen

QStringList list = QSettings::AllKeys();
abfrage, bekomme ich dann:

"System_1.0/Eigenschaften"

was meinst du da jetzt genau mit
Eigenschaften"->toStringList()
lg
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

reinki0013 hat geschrieben:wenn ich jetzt mit

Code: Alles auswählen

QStringList list = QSettings::AllKeys();
abfrage, bekomme ich dann:

"System_1.0/Eigenschaften"
Das ist dann jetzt dein (bisher) einziger Key.
Wobei dein Code so natürlich nicht funktioniert ;)

Code: Alles auswählen

QSettings settings;
QStringList keys = settings.allKeys();
allKey() ist keine statische Funktion.
was meinst du da jetzt genau mit
Eigenschaften"->toStringList()

Code: Alles auswählen

QString key = "System_1.0/Eigenschaften";  // Dein Key - du willst aber wohl alle Keys
QStringList value = settings.value(key).toStringList();
reinki0013
Beiträge: 174
Registriert: 11. November 2008 09:37
Wohnort: AUT

Beitrag von reinki0013 »

@franzf

ich danke dir recht herzlich für deine geduld mit mir :roll:

ich habe es jetzt so hinbekommen wie ich es wollte.
funktioniert perfekt, auch das durchsuchen sowie das speichern...

einfach eine perfekte lösung (für mich halt)...
was habe ich daraus gelernt -> QStringList kann man ebenso in QSettings speichern... :lol:

danke auf jedenfall,

lg
Antworten