Копировать и копировать неправильно работает со списком строк

Я получил большой XML-файл, и я хочу сохранить каждый идентификатор, источник и цель в списке строк для генерации после успешного импорта в списки строк построить запрос к MySQL.

Вот фрагмент моего XML:

xliff version="1.1">
 <file original="Xliff Demo" source-language="EN" target-language="DE" datatype="html">
 <header>
 <skl>
 <external-file uid="017dbcf0-c82c-11e2-ba2b-005056c00008" href="skl\simple.htm.skl"/>
 </skl>
 </header>
 <body>
 <trans-unit id="00ffmnpB5wBV5KFqBxuHLi4fwJvvuB">
 <source xml:lang="EN">1lnRUfBBeHtbS96uULSht42VNMN7XE4qt9JrOcWhtoTuhnbAQ9</source>
 <target xml:lang="DE">zZvOLJfLCy9oP5GQYfEqw5LAeC2ESAxRmVe1JyQdmJ1eG2jz1N</target>
 <note/></trans-unit>
 <trans-unit id="00kjUwy1rJ54bEGYp7XZvtBiY32pmj">
 <source xml:lang="EN">HXOQLUWkfJg206vRw8lyWhCWChOacVxbMukfQ0HUdNHSI18GG4</source>
 <target xml:lang="DE">8dsX38mezeZ0w0w37LI66CDRuI8gBD23zT5KR4iqYNv3IGUgH0</target>
 <note/></trans-unit>
 <trans-unit id="00kk3Af8SFpHyelAaYrgK58b9GbIDj">
 <source xml:lang="EN">wQFxZiCiRsSNWs20G4WXAmDBRdRL6fcrrJnCgtbiXGSfHzpYrT</source>
 <target xml:lang="DE">oFVTUdPkExOhISYofIImLsnVKd3NSZg32tyeP5iRxRZdmuYQDy</target>
 <note/></trans-unit>
 <trans-unit id="00Ky2dmDU9wGTWBnJxeL9b9gkts5UQ">
 <source xml:lang="EN">nHQcjAW02lWe0SyOhqGtyqUhpwQ8qgWX3rUynMRf4BDHfVdHOC</source>
 <target xml:lang="DE">0CURp1dcZydB1V2rEZ1lnOhmYufOYbrLbh84e1ZnALlzZPVq4F</target>
 <note/></trans-unit>
 <trans-unit id="00pMSFlBfA3bJ8Xy9I78wz6XisPYcV">
 <source xml:lang="EN">IuhtaVnZtF67nxKz5dbmuy8BEMTs2X1120FzDtIplKF2Me5AsQ</source>
 <target xml:lang="DE">1BGSJQDZBm4UW974pucnX3XHuYOQYpC7nTcIH01rbKlOkVi9bo</target>
 <note/></trans-unit>
 <trans-unit id="012w2kb2d1Lo6NbJLE0BawThzsSuCJ">
 <source xml:lang="EN">0RoniOGZ7V7WTF1YQg59B8jBhRxnLVXscC1LOGPzKPYRs76oIz</source>
 <target xml:lang="DE">gyw15fkHTni2aUGWI5qiPHEz8vsJJJsW4OOqKwGYL1qzfUVfLO</target>
 <note/></trans-unit>
...
..
..

Поэтому я пытаюсь сохранить каждую запись идентификатора транс-единицы, источника xml:lang"EN", цели xml:lang="DE" в отдельном списке строк, но только значения.

Вот мой код:

{ -----------  Import Procedure ------------ }
procedure TForm2.Button2Click(Sender: TObject);
var
  xmlFile, idList, sourceList, targetList: TStringList; // StringListe wo die Xml Datei eingelesen wird
  i: Integer;
  id, source, target: String;
  idTmp, idTmp2, sourceTmp, sourceTmp2, targetTmp, targetTmp2: Integer;
begin
  try
    xmlFile := TStringList.Create;
    idList := TStringList.Create;
    sourceList := TStringList.Create;
    targetList := TStringList.Create;

    if OpenDialog1.Execute then
      xmlFile.LoadFromFile(OpenDialog1.FileName);

      {Debug}
        //ShowMessage(IntToStr(XmlFile.Count));   Ausgabe der Zeilenlänge
        //ShowMessage(XmlFile[8]);                // Ausgabe der Zeile 8
      {/Debug}

      for i := 0 to xmlFile.Count-1 do // Über alle Zeilen der StringList gehen und folgendes tun:
        begin // Code pro Zeile

          {id}
          idTmp  := Pos('<trans-unit id="', xmlFile.Strings[i])+16;  //  Sucht nach trans-unit id   (16 ist die Anzahl der Länge vom Suchstring in dem Fall trans-unit id 16 Stellen lang
          if idTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
          begin
            idTmp2 := Pos('"', xmlFile.Strings[i], idTmp); // Ermittelt die Position vom Ende des Strings (")
            idList.Add(Copy(xmlFile.Strings[i], idTmp, idTmp2-idTmp));
          end;

          {source}
          sourceTmp  := Pos('<source xml:lang="EN">', xmlFile.Strings[i])+22;
          if sourceTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
          begin
            sourceTmp2 := Pos('<', xmlFile.Strings[i], sourceTmp); // Ermittelt die Position vom Ende des Strings (")
            sourceList.Add(Copy(xmlFile.Strings[i], sourceTmp, sourceTmp2-sourceTmp));
          end;

          {target}
          targetTmp  := Pos('<target xml:lang="DE">', xmlFile.Strings[i])+22;
          if targetTmp > 5 then // Überprüfen ob was gefunden wurde (Ungleich 0)
          begin
            targetTmp2 := Pos('<', xmlFile.Strings[i], targetTmp); // Ermittelt die Position vom Ende des Strings (")
            targetList.Add(Copy(xmlFile.Strings[i], targetTmp, targetTmp2-targetTmp));
          end;
        end;

      StartPerformance;
      UniConnection1.Open;
  finally
    ListBox1.items.assign(idList);
    ListBox2.items.assign(sourceList);
    ListBox3.items.assign(targetList);
    ShowMessage('Import in StringListen fertiggestellt.');
    xmlFile.Free;
    idList.Free;
    sourceList.Free;;
    targetList.Free;
  end;
end;

Но это не работает так, как я хочу. Моя проблема в том, что он также сохраняет пустые строки в списке строк и прочем мусоре. Я действительно не нахожу свою ошибку, и я впервые использую эту функцию копирования / размещения.

Вот скриншот

Что я должен изменить, чтобы исправить мою проблему и сохранить только правильные строки в моих 3 списках строк?

2 ответа

Решение

Вот:

idTmp  := Pos('<trans-unit id="', xmlFile.Strings[i])+16;  
if idTmp > 5 then 
  ...

idTmp всегда будет больше 5 - вы добавляете 16 к нему независимо от того, что и он всегда возвращает положительное значение (или ноль, если нет совпадения).

Самое простое изменение здесь будет:

 idTmp  := Pos('<trans-unit id="', xmlFile.Strings[i]);  
 if idTmp > 0 then begin //Pos returns 0 if no match found
   idTmp := idTmp + 16;
   idTmp2 := PosEx('"', xmlFile.Strings[i], idTmp); 
   idList.Add(Copy(xmlFile.Strings[i], idTmp, idTmp2-idTmp));
 end;

Изменение для двух других блоков будет следовать аналогичным образом.

Вы заметите, что я использовал StrUtils.PosEx здесь для idTmp2 - Я не знаю, как ваш код скомпилирован с использованием Pos для второй функции...

редактировать

Хорошо, похоже, что Pos был изменен в XE3 для включения смещенных перегрузок. Если ваша цель здесь - производительность (как это видно из комментариев), вы, вероятно, должны прочитать это:

http://qc.embarcadero.com/wc/qcmain.aspx?d=111103

Кроме того, что, я думаю, очень важно, это действительно ужасный способ разбора XML. Я настоятельно рекомендую вам прочитать некоторые исходные коды из проектов, которые уже делают это, чтобы лучше понять, как вы должны подходить к проблеме. Некоторые примеры могут быть:

Возможно, вам следует подумать об использовании интерфейса IXMLDocument для загрузки XML-файла в структуру данных и последующего заполнения ваших списков строк.

Пример был размещен здесь: /questions/22734602/kak-sozdat-etot-xml-s-delphi/22734625#22734625

Другие вопросы по тегам