Delphi 7 чтение и обработка XML-файла, как и какой компонент - обновить - PullRequest
4 голосов
/ 25 января 2012

У меня есть клиент, который предоставляет файл со смешанными запятыми данными и XML. Разделяемая запятая не является проблемой, но xml для меня все новое.

Я попытался найти компонент, который будет делать то, что мне нужно (omnixml - отменен - ​​использование встроенного в xml компонента delphi ) представляется возможным ...

У меня есть данные, подобные следующим:

<Passengers>
  <Passenger>
<No>1</No>
<Title>mrs</Title>
<ForeName>Anne</ForeName>
<SurName>XXXXXXXX</SurName>
<Age>33</Age>
<UWStatus>accept</UWStatus>
<Screening>
  <ScreeningData>
    <ScreeningPath SL="2.2" DATA="1">
      <MedicalRisk>4.01</MedicalRisk>
      <rootConditionId>1292</rootConditionId>
      <isAMT>false</isAMT>
      <regionId>4</regionId>
      <isWinterSport>false</isWinterSport>
      <isRetScheme>false</isRetScheme>
      <isPair>false</isPair>
      <LinkedCondition>3</LinkedCondition>
      <LinkedConditions>
        <LinkedCondition Name="High blood pressure" ICD="401.9" Type="D"/>
        <LinkedCondition Name="Renal failure" ICD="586" Type="D"/>
        <LinkedCondition Name="Abdominal aortic aneurysm" ICD="441.4" Type="I"/>
        <LinkedCondition Name="Peripheral vascular disease" ICD="443.9" Type="I"/>
        <LinkedCondition Name="Angina" ICD="414.9" Type="IS"/>
        <LinkedCondition Name="Enlarged heart" ICD="425" Type="IS"/>
        <LinkedCondition Name="Heart attack" ICD="414.9" Type="IS"/>
        <LinkedCondition Name="Heart failure" ICD="428.0" Type="IS"/>
        <LinkedCondition Name="Mini stroke" ICD="435.9" Type="IS"/>
        <LinkedCondition Name="Stroke" ICD="434" Type="IS"/>
      </LinkedConditions>
      <ScreeningHistory>
        <DeclaredCondition Score="3.56">
          <conditions>
            <Condition>
              <id>1292</id>
              <parentid>-1</parentid>
              <name>Epilepsy</name>
              <questions>
                <Question>
                  <id>1</id>
                  <Text>If awake#$ do you normally lose consciousness during a fit/seizure?</Text>
                  <currentAnswer>
                    <Text>Yes</Text>
                    <id>1</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>2</id>
                  <Text>How many fits/seizures causing loss of consciousness have you had in the last four weeks?</Text>
                  <currentAnswer>
                    <Text>0</Text>
                    <id>1</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>3</id>
                  <Text>How many fits/seizures causing loss of consciousness have you had in the last six months?</Text>
                  <currentAnswer>
                    <Text>0</Text>
                    <id>1</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>4</id>
                  <Text>How many unplanned hospital admissions have you had for epilepsy/seizures in the last year?</Text>
                  <currentAnswer>
                    <Text>1</Text>
                    <id>2</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>5</id>
                  <Text>How many different medicines do you take for your epilepsy/seizures?</Text>
                  <currentAnswer>
                    <Text>1</Text>
                    <id>2</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>6</id>
                  <Text>How long ago was your first fit/seizure?</Text>
                  <currentAnswer>
                    <Text>6 to 12 months ago</Text>
                    <id>2</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>7</id>
                  <Text>If not already declared to us#$ is your epilepsy/seizures caused by:</Text>
                  <currentAnswer>
                    <Text>None of these</Text>
                    <id>4</id>
                  </currentAnswer>
                </Question>
              </questions>
              <currentQuestionId>7</currentQuestionId>
              <isAMTExclusion>false</isAMTExclusion>
              <isWSExclusion>false</isWSExclusion>
              <Score>3.56</Score>
              <ICD>345.9</ICD>
              <Deterioration>0</Deterioration>
              <isOkForWS>true</isOkForWS>
              <isOkForAMT>true</isOkForAMT>
              <exclusionType>None</exclusionType>
            </Condition>
          </conditions>
        </DeclaredCondition>
        <DeclaredCondition Score="1.45">
          <conditions>
            <Condition>
              <id>1332</id>
              <parentid>-1</parentid>
              <name>Blood pressure</name>
              <questions>
                <Question>
                  <id>1</id>
                  <Text>How many medicines does your doctor advise you to take for high blood pressure?</Text>
                  <currentAnswer>
                    <Text>1</Text>
                    <id>2</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>2</id>
                  <Text>Has your dose been increased or have you been prescribed a new tablet in the last six months?</Text>
                  <currentAnswer>
                    <Text>No</Text>
                    <id>2</id>
                  </currentAnswer>
                </Question>
                <Question>
                  <id>3</id>
                  <Text>Have you been advised to take a medication to lower your cholesterol level?</Text>
                  <currentAnswer>
                    <Text>No</Text>
                    <id>1</id>
                  </currentAnswer>
                </Question>
                <Question MQ="2">
                  <id>4</id>
                  <Text>Have you ever been a smoker?</Text>
                  <currentAnswer>
                    <Text>Yes - gave up less than a year ago</Text>
                    <id>3</id>
                  </currentAnswer>
                </Question>
              </questions>
              <currentQuestionId>4</currentQuestionId>
              <isAMTExclusion>false</isAMTExclusion>
              <isWSExclusion>false</isWSExclusion>
              <Score>1.45</Score>
              <ICD>401.9</ICD>
              <Deterioration>1</Deterioration>
              <isOkForWS>true</isOkForWS>
              <isOkForAMT>true</isOkForAMT>
              <exclusionType>None</exclusionType>
              <LinkedConditions>
                <LinkedCondition Name="High blood pressure" ICD="401.9" Type="D"/>
                <LinkedCondition Name="Renal failure" ICD="586" Type="D"/>
                <LinkedCondition Name="Abdominal aortic aneurysm" ICD="441.4" Type="I"/>
                <LinkedCondition Name="Peripheral vascular disease" ICD="443.9" Type="I"/>
                <LinkedCondition Name="Angina" ICD="414.9" Type="IS"/>
                <LinkedCondition Name="Enlarged heart" ICD="425" Type="IS"/>
                <LinkedCondition Name="Heart attack" ICD="414.9" Type="IS"/>
                <LinkedCondition Name="Heart failure" ICD="428.0" Type="IS"/>
                <LinkedCondition Name="Mini stroke" ICD="435.9" Type="IS"/>
                <LinkedCondition Name="Stroke" ICD="434" Type="IS"/>
              </LinkedConditions>
            </Condition>
          </conditions>
        </DeclaredCondition>
      </ScreeningHistory>
    </ScreeningPath>
  </ScreeningData>
</Screening>

xml все поставляется в одном поле без пробелов (я отформатировал это), и там, где присутствует более одного человека, это выглядит как новая запись пассажира.

Мне нужно иметь возможность обработать это и извлечь такие вещи, как

Поля Заголовок / Имя / Фамилия из записи пассажира а затем из ветви и из того, к чему он относится, повторяется для каждого ответа на каждое условие.

Я думаю, это довольно легко, но я борюсь.

Код, который у меня пока есть ...

Первый человек прав, 2-й теряет одного из своих братьев и сестер? Есть ли ошибка или это я?

StartItemNode:=XMLDoc.DocumentElement.ChildNodes.First;
ANode := StartItemNode;

repeat
  Title := ANode.ChildNodes['Title'].Text;
  Forename := ANode.ChildNodes['ForeName'].Text;
  Surname := ANode.ChildNodes['SurName'].Text;
  Age:=Anode.ChildNodes['Age'].Text;
  memo1.Lines.Add(Title+' '+Forename+' '+Surname+' '+Age);

  CNode:=Anode.ChildNodes.FindNode('Screening');
  CNode:=CNode.ChildNodes.FindNode('ScreeningData');
  CNode:=CNode.ChildNodes.FindNode('ScreeningPath');
  CNode:=CNode.ChildNodes.FindNode('ScreeningHistory');
  CNode:=Cnode.ChildNodes.FindNode('DeclaredCondition');
  CNode:=Cnode.ChildNodes.FindNode('conditions');
  CNode:=Cnode.ChildNodes.FindNode('Condition');
  (* Missing the 2nd illness on the 2nd node - but why *)

  repeat
   ill:=Cnode.ChildNodes['name'].text;
   memo1.Lines.add(ill);
   Unode:=Cnode;
   CNode:=Cnode.NextSibling;
  until cnode=nil;

Буду признателен за любую помощь, пожалуйста. С уважением Фил

Ответы [ 5 ]

2 голосов
/ 26 января 2012

Мне действительно нравится использовать NativeXML от SimDesign.Он имеет приличные документы и с открытым исходным кодом.http://www.simdesign.nl/nativexml.html

2 голосов
/ 26 января 2012

Вам не нужна отдельная библиотека: Delphi идет уже с одной

Создайте интерфейсный блок для вашего (неформатированного) XML-файла с помощью Мастер привязки данных XML (только для D7 в корпоративной версии), см. Файл> Создать> Прочее> Новый> Данные XML Связывание . Настройте по своему усмотрению, но просто пройдя каждую страницу мастера нажатием OK, по умолчанию все работает отлично. (Обратите внимание, что настройки по умолчанию для других версий Delphi могут отличаться от моих.) Хотя мне лично нравится избавляться от суффикса «Тип» для каждого типа интерфейса. (Как и для имен типов классов, но это не вариант в мастере, так что вы можете сделать это вручную.)

См. этот ответ в качестве примера или дополнительные инструкции.

Обратите внимание, что этот мастер предназначен только для удобства: вы также можете работать только с TXMLDocument (на вкладке Интернет палитры компонентов). Получить корневой узел с помощью ADocument.DocumentElement, дочерние узлы с помощью Node.ChildNodes.FindNode('Node name') и его значения с помощью Node.ChildValues['Value name'].

2 голосов
/ 26 января 2012

Мы широко использовали TurboPower XML Partner в старых версиях Delphi.(Не могу вспомнить, использовали ли мы это в Delphi 7).Вот ссылка на последнюю версию на SourceForge: http://sourceforge.net/projects/tpxmlpartner/. Вы можете найти предыдущую версию, которая будет работать для вас.

Вы также можете использовать объект xml com, найденный в msxml.длл.Это работает довольно хорошо.Вот еще немного информации об этом: https://stackoverflow.com/a/1391413/758074. Видимо "Объект TXMLDocument (для delphi 7), расположенный в XMLDoc.pas, является Wrapper версии MSXML на 4 и менее."Но если вы импортируете версию 6, вы должны быть в хорошей форме.

1 голос
/ 26 января 2012

Для TXmlDocument Msxml встроен в D7 (или D6, как я использую, примерно то же самое).

Существует также старая версия встроенного XDOM Дитера Келера, или вы могли бызагрузите его обновленный ADOM с www.philo.de/xml/ (с помощью обертки IDomNode с github.com/Midiar/adomxmldom).Они реализованы на языке Паскаль - хорошо для отладки.ADOM предоставляет вам функциональность XPath.

Редактировать: Msxml также имеет XPath (и XSLT).

0 голосов
/ 28 января 2012

Я решил проблему и использовал встроенный в Delphi7 объект XML.И для нескольких людей.

Это было намного сложнее, чем я думал вначале.

Как и в приведенной выше структуре, я обнаружил, что если вы заявили, что у вас все в порядке, но если это подразумевается, например, выу вас высокое кровяное давление, поэтому, возможно, вы повысили уровень холестерина (правописание!), тогда последующий вопрос не относится к основной ветви заявленных условий, а к условиям.

Код, следующий за этим, работает для этого - большая частьповторяющихся цитат, НО я хотел, чтобы это работало, а не выглядело симпатично ..

И я должен признать, что узнал о XML больше, чем хотел бы ... И большое спасибо :-) ко всей помощи, чтобыло предложено - много чтения о переполнении стека и поиск в Google, и теперь у меня есть результат!

procedure TForm1.Button1Click(Sender: TObject);
var
 StartItemNode:IXMLNode;
 ANode:IXMLNode;
 CNode:IXMLNode;
 LNode:IXMLNode;
 QNode:IXMLNode;
 UNode:IXMLNode;
 hnode:ixmlnode;
INode:IXMLNode;
number:widestring;  
Title:widestring;
Forename:widestring;
Surname:widestring;
Age:widestring;
ill:widestring;
quest:widestring;
answer:widestring;
first:boolean;
who:string;
begin
 opendialog1.Execute;
 who:=extractfilepath(opendialog1.FileName)+extractfilename(opendialog1.filename)
 +'_TXT.TXT';
 XMLDOC.FileName:=opendialog1.FileName;

 XMLDoc.Active:=True;

memo1.Clear;
XMLDOC.SaveToFile('c:\philxx.xml');

StartItemNode:=XMLDoc.DocumentElement.ChildNodes.First;
ANode := StartItemNode;

memo1.Lines.add('Filename '+opendialog1.FileName);
if anode<>nil then
begin

repeat
  memo1.Lines.Add('====== New Person ======');
  number :=anode.childnodes['number'].Text;
  Title := ANode.ChildNodes['Title'].Text;
  Forename := ANode.ChildNodes['ForeName'].Text;
  Surname := ANode.ChildNodes['SurName'].Text;
  Age:=Anode.ChildNodes['Age'].Text;
  memo1.lines.add(number);
  memo1.Lines.Add(Title+' '+Forename+' '+Surname+' '+Age);

  CNode:=Anode.ChildNodes.FindNode('Screening');
  CNode:=CNode.ChildNodes.FindNode('ScreeningData');
  CNode:=CNode.ChildNodes.FindNode('ScreeningPath');
  CNode:=CNode.ChildNodes.FindNode('ScreeningHistory');

  HNode:=Cnode.ChildNodes.FindNode('DeclaredCondition');
  while hnode<>nil do
  begin
    unode:=hnode;
  memo1.lines.add('==== Illnesses ===');
  if unode<>nil then
  begin
   UNode:=Unode.ChildNodes.FindNode('conditions');
   Cnode:=Unode;
   Inode:=CNode.ChildNodes.FindNode('Condition');
  while unode<>nil do
  begin
   ill:=Inode.ChildNodes['name'].text;
   memo1.Lines.add(ill);
   lnode:=Unode;
   unode:=unode.nextsibling;
   if unode=nil then
    begin
     unode:=lnode;
     inode:=inode.NextSibling;
     if inode=nil then unode:=nil;
    end
    else
    begin
     CNode:=Unode.ChildNodes.FindNode('conditions');
     Inode:=CNode.ChildNodes.FindNode('Condition');
    end;


  end;

  end;
   hnode:=hnode.nextsibling;
  end;
  CNode:=Anode.ChildNodes.FindNode('Screening');
  CNode:=CNode.ChildNodes.FindNode('ScreeningData');
  CNode:=CNode.ChildNodes.FindNode('ScreeningPath');
  CNode:=CNode.ChildNodes.FindNode('ScreeningHistory');
  HNode:=Cnode.ChildNodes.FindNode('DeclaredCondition');


  while hnode<>nil do
  begin
    unode:=hnode;

  (* Gets all the questions but seems to have same issue with missing questions for 2nd illness *)
  if unode<>nil then
  begin
   UNode:=Unode.ChildNodes.FindNode('conditions');
   Cnode:=Unode;
   Inode:=CNode.ChildNodes.FindNode('Condition');



  while unode<>nil do
   begin
     QNode:=inode.ChildNodes.FindNode('questions');
     if qnode=nil then
      begin
       memo1.lines.add('=== No questions for Illness === ');
      end;
     if qnode<>nil then
      begin
        qNode:=qNode.ChildNodes.FindNode('Question');
        memo1.Lines.add('==== New Questions ====');
        while qnode<>nil do
         begin
          quest:=qnode.ChildNodes['Text'].text;
          memo1.Lines.add(quest);
          answer:=qnode.ChildNodes['currentAnswer'].ChildNodes['Text'].text;
          memo1.lines.add(answer);
          qNode:=qnode.NextSibling;
         end;
      end;
     lnode:=unode;
     unode:=unode.NextSibling;
     if unode=nil then
     begin
       unode:=lnode;
       inode:=inode.NextSibling;
       if inode=nil then unode:=nil;
     end
     else
     begin
      CNode:=Unode.ChildNodes.FindNode('conditions');
      Inode:=CNode.ChildNodes.FindNode('Condition');
     end;
   end;
  end;
   hnode:=hnode.nextsibling;
  end;

  ANode := ANode.NextSibling;
until ANode = nil;
end
  else memo1.lines.Add('No Illness or Questions Found ');
  memo1.Lines.SaveToFile(who);
  showmessage('done');
...