Search code examples
xmldelphidelphi-7

delphi 7 reading and processing xml file how and which component - update


I have a client who is supplying a file with mixed comma seperated data and xml. The comma seperated is not a problem but the xml is all new to me.

I have tried to find a component to do what i need (omnixml -abandoned - using delphi built in xml component) seems possible...

I have data like the following :

<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>

The xml is all supplied in one field no spaces (i have formatted this) and where there is more than one person it appears this appears as a new passenger record.

I need to be able to process this and extract things like

Title/Forename/Surname fields from the passenger record and then from the branch and from the and which it relates to that is repeated for each answer to each condition.

I think it is fairly easy but I am struggling.

Code I have so far....

The first person is correct the 2nd one looses one of its siblings? Is there a bug or is it me?

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;

Any help would be grateful received please. Regards Phil


Solution

  • I did fix the problem and used Delphi7 built in XML object. And for multiple people.

    It was alot harder than I first thought.

    As on the structure above I found if you declared a medical condition all was well but if the condition is implied e.g you have high blood pressure so therefore you may have raised cholesteral (spelling!) then the subsequent question are not under the main declared conditions branch but under conditions.

    The code following does work for this - there is a large part of repeated quote BUT I wanted it to work rather than look pretty..

    And I must admit i have learnt more about XML than I wanted to lol... And big thaks :-) to all the help that was offered - a lot of reading on stack overflow and some google searching and I now have a result!

    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');