Seite 1 von 1

Probleme mit einer Xml-Datei...

Verfasst: 25. Mai 2010 15:17
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

Verfasst: 25. Mai 2010 15:28
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

Verfasst: 25. Mai 2010 15:31
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

Verfasst: 25. Mai 2010 19:09
von upsala
Schau dir mal die Doku zu QDomDocument an.

Verfasst: 25. Mai 2010 19:10
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!

Verfasst: 26. Mai 2010 09:01
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

Verfasst: 26. Mai 2010 11:16
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.

Verfasst: 26. Mai 2010 11:31
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 ...

Verfasst: 27. Mai 2010 07:58
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

Verfasst: 27. Mai 2010 11:37
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

Verfasst: 27. Mai 2010 12:32
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

Verfasst: 27. Mai 2010 12:40
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 ;)

Verfasst: 27. Mai 2010 13:22
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

Verfasst: 27. Mai 2010 15:58
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();

Verfasst: 27. Mai 2010 18:32
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