how Adding a node in an XML file with QXmlStreamWr

2019-08-14 19:20发布

I created an xml file with QXmlStreamWriter, then I want to add each time a block before closing the xml file. but ,what I am trying to do is add the block to the end of the file with a startDocument, so in every addition I have a XML header, for this I got an error while reading the document, the program reads the first block and when it goes to the second block, it shows me "xml declaration not at strat of document" this is my file:

<?xml version="1.0" encoding="UTF-8"?>
<Fiche_Du_Patient>
<INFORMATIONS_DU_PATIENT>
 <Hopital>a </Hopital>
  <Num_dossier>b</Num_dossier>
  <Nom_et_prenom>c</Nom_et_prenom>
  <Date_de_naissance>11111</Date_de_naissance>
  <Sex>F </Sex>
  <Age>26</Age>
  <Date_examen>22222</Date_examen>
  <Medecin_traitant></Medecin_traitant>
  <Rapport></Rapport>
</INFORMATIONS_DU_PATIENT>
<NUMERO_SLICE>
  <Num_Slice>1</Num_Slice>
   <COORDONEES>
    <X1>7.32896</X1>
    <Y1>10.6362</Y1>
    <X2>8.96937</X2>
    <Y2>9.28687</Y2>
  </COORDONEES>
  <DISTANCE>
   <Distance_en_cm>2.1241</Distance_en_cm>
  </DISTANCE>
  <ANGLE>
   <Angle>7</Angle>
  </ANGLE>
 </NUMERO_SLICE>
</Fiche_Du_Patient>
<?xml version="1.0" encoding="UTF-8"?>
  <NUMERO_SLICE>
   <Num_Slice>2</Num_Slice>
    <COORDONEES>
     <X1>7.80521</X1>
     <Y1>10.3452</Y1>
     <X2>9.49854</X2>
     <Y2>9.525</Y2>
   </COORDONEES>
   <DISTANCE>
   <Distance_en_cm>1.88152</Distance_en_cm>
   </DISTANCE>
   <ANGLE>
    <Angle>1</Angle>
   </ANGLE>
 </NUMERO_SLICE>
<?xml version="1.0" encoding="UTF-8"?>
  <NUMERO_SLICE>
   <Num_Slice>3</Num_Slice>
    <COORDONEES>
     <X1>6.69396</X1>
     <Y1>10.8215</Y1>
     <X2>9.26042</X2>
     <Y2>9.47208</Y2>
    </COORDONEES>
    <DISTANCE>
     <Distance_en_cm>2.89957</Distance_en_cm>
    </DISTANCE>
    <ANGLE>
     <Angle>25</Angle>
    </ANGLE>
  </NUMERO_SLICE>

this method is false, what I want to get is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Fiche_Du_Patient>
<INFORMATIONS_DU_PATIENT>
    <Hopital>a </Hopital>
    <Num_dossier>b</Num_dossier>
    <Nom_et_prenom>c</Nom_et_prenom>
    <Date_de_naissance>11111</Date_de_naissance>
    <Sex>F </Sex>
    <Age>26</Age>
    <Date_examen>22222</Date_examen>
    <Medecin_traitant></Medecin_traitant>
    <Rapport></Rapport>
</INFORMATIONS_DU_PATIENT>
<NUMERO_SLICE>
    <Num_Slice>1</Num_Slice>
    <COORDONEES>
        <X1>7.32896</X1>
        <Y1>10.6362</Y1>
        <X2>8.96937</X2>
        <Y2>9.28687</Y2>
    </COORDONEES>
    <DISTANCE>
        <Distance_en_cm>2.1241</Distance_en_cm>
    </DISTANCE>
    <ANGLE>
        <Angle>7</Angle>
    </ANGLE>
</NUMERO_SLICE>
<NUMERO_SLICE>
<Num_Slice>2</Num_Slice>
<COORDONEES>
  <X1>7.80521</X1>
  <Y1>10.3452</Y1>
  <X2>9.49854</X2>
  <Y2>9.525</Y2>
</COORDONEES>
<DISTANCE>
  <Distance_en_cm>1.88152</Distance_en_cm>
</DISTANCE>
<ANGLE>
  <Angle>1</Angle>
</ANGLE>
</NUMERO_SLICE>
 <NUMERO_SLICE>
 <Num_Slice>3</Num_Slice>
<COORDONEES>
  <X1>6.69396</X1>
  <Y1>10.8215</Y1>
  <X2>9.26042</X2>
  <Y2>9.47208</Y2>
</COORDONEES>
<DISTANCE>
  <Distance_en_cm>2.89957</Distance_en_cm>
</DISTANCE>
<ANGLE>
  <Angle>25</Angle>
</ANGLE>
</NUMERO_SLICE>
</Fiche_Du_Patient>

As you see < NUMERO_SLICE > block repeats with each addition of new parameters. Normally this block is added before the < / Fiche_Du_Patient> but I have not found a way with QXmlStreamWriter (I am a beginner in xml) I searched the net, I found nothing about this.

is it exist, please, a method that adds the < NUMERO_SLICE> block each time before ?

cordially

标签: c++ xml qt
2条回答
欢心
2楼-- · 2019-08-14 20:11

If you choose to continue with QXmlStreamReader/Writer, you'll need:

  1. Read the contents using QXmlStreamReader
  2. While also writing out to QXmlStreamWriter

Below is an example if what you'd need to do. Keep in mind that there are a number of other cases to check for, like isComment(), copying attributes, etc:

QString xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
              "<data>"
                "<value>1</value>"
                "<value>2</value>"
              "</data>";

QString out;
QXmlStreamWriter writer(&out);

QXmlStreamReader reader(xml);
while(!reader.atEnd())
{
  if(reader.isStartDocument())
    writer.writeStartDocument();

  if(reader.isStartElement())
  {
    writer.writeStartElement(reader.name().toString());

    // New elements are appended here
    if(reader.name() == "data")
    {
      writer.writeStartElement("newValue");
      writer.writeCharacters("newValue");
      writer.writeEndElement();
    }
  }

  if(reader.isCharacters())
    writer.writeCharacters(reader.text().toString());

  if(reader.isEndElement())
    writer.writeEndElement();

  if(reader.isEndDocument())
    writer.writeEndElement();

  reader.readNext();
}

qDebug() << out;

The output (formatted):

<?xml version="1.0"?>
<data>
  <newValue>newValue</newValue>
  <value>1</value>
  <value>2</value>
</data>
查看更多
何必那么认真
3楼-- · 2019-08-14 20:25

I think that only this hack can avoid to read full XML to memory and rewrite:

 {
    QString path("/home/carlo/test/x.xml");
    QString ctag = "</Fiche_Du_Patient>\n";

    QFile file(path);
    qint64 s = file.size();
    if (s > 0) {
        file.open(QFile::ReadWrite);
        if (file.seek(s - ctag.length()))
            Q_ASSERT(file.pos() == s - ctag.length());

    } else
        file.open(QFile::WriteOnly);

    QXmlStreamWriter xmlWriter(&file);
    xmlWriter.setAutoFormatting(true);
    xmlWriter.setAutoFormattingIndent(2);

    if (s == 0) {
        xmlWriter.writeStartDocument();
        xmlWriter.writeStartElement("Fiche_Du_Patient");
    }

    xmlWriter.writeStartElement("NUMERO_Patient");
    xmlWriter.writeTextElement("Num_Patient", "123");
    xmlWriter.writeTextElement("Nom_et_prenom", s > 0 ? "appending" : "creating");
    xmlWriter.writeTextElement("Date_de_naissance", s > 0 ? "more date" : "first date");
    xmlWriter.writeEndElement();

    if (s == 0) {
        xmlWriter.writeEndElement();
        xmlWriter.writeEndDocument();
    }
    else
        QTextStream(&file) << ctag;
}

this produce correct XML, but the format output isn't optimal (the nice indentation is lost). A better way would parse the last tag, without hard coding it.

查看更多
登录 后发表回答