【问题标题】:delphi 7 reading and processing xml file how and which component - updatedelphi 7读取和处理xml文件如何以及哪个组件-更新
【发布时间】:2012-01-25 12:48:59
【问题描述】:

我有一个客户正在提供一个包含混合逗号分隔数据和 xml 的文件。逗号分隔不是问题,但 xml 对我来说是全新的。

我试图找到一个组件来做我需要的事情(omnixml -已放弃 - 使用 delphi 内置的 xml 组件)似乎是可能的......

我有如下数据:

<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 全部在一个字段中提供,没有空格(我已对此进行了格式化),并且如果有多个人,它会显示为新的乘客记录。

我需要能够处理这个并提取类似的东西

乘客记录中的职务/姓名/姓氏字段 然后从分支和与它相关的 and 对每个条件的每个答案重复。

我认为这很容易,但我很挣扎。

到目前为止我的代码......

第一个人是正确的第二个人失去了一个兄弟姐妹?有错误还是我?

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;

如果收到任何帮助,将不胜感激。 问候 菲尔

【问题讨论】:

  • This question 似乎提供了使用 OmniXML 所需的所有信息。
  • 嗨,Ken,我试过了,但我还在苦苦挣扎,我的问题是如果我做一个循环来选择主乘客节点,那么我如何子选择其他节点,如
  • 好的。试试this link,看看它是否能让事情变得更清楚。 :)
  • Ken 试过这对我的文件不起作用,基本上最终选择了每个人的所有兄弟数据 - 所以如果你有 2 个人记录,你会得到第一个人的所有疾病和问题。放弃并尝试上述方法。
  • 你能把别人的XML数据加到上面的XML数据中吗?当前的示例数据仅适用于 1 人(并且不完整!)。如果我们可以测试更多人,那就太好了,因为您对此有特别的麻烦。

标签: xml delphi delphi-7


【解决方案1】:

我们在旧版本的 Delphi 中广泛使用了 TurboPower XML Partner。 (不记得我们是否在 Delphi 7 中使用过它)。这是 SourceForge 上最新版本的链接:http://sourceforge.net/projects/tpxmlpartner/。您或许可以找到适合您的旧版本。

您还可以使用 msxml.dll 中的 xml com 对象。它工作得很好。以下是有关它的更多信息:https://stackoverflow.com/a/1391413/758074。显然“位于 XMLDoc.pas 中的对象 TXMLDocument (for delphi 7) 是 MSXML 4 o less 版本的包装器。”。但如果你导入第 6 版,你应该状态良好。

【讨论】:

    【解决方案2】:

    您不需要单独的库:Delphi 已经提供了一个

    使用 XML 数据绑定向导(仅适用于企业版中的 D7)为您的(未格式化的)XML 文件创建一个接口单元,请参阅文件 > 新建 > 其他 > 新建 > XML数据绑定。随心所欲地进行调整,但默认情况下只需通过单击“确定”来传递每个向导页面就可以了。 (请注意,其他 Delphi 版本的默认设置可能与我的不同。)虽然我个人喜欢摆脱的一件事是每个接口类型的“类型”后缀。 (以及类类型名称,但这不是向导中的选项,因此您可以手动进行。)

    请参阅this answer 作为示例或了解更多说明。

    请注意,此向导只是为了方便起见:您也可以只使用TXMLDocument(在组件选项板的 Internet 选项卡上)。以ADocument.DocumentElement获取根节点,以Node.ChildNodes.FindNode('Node name')获取子节点及其值以Node.ChildValues['Value name']获取。

    【讨论】:

    • 我同意 NGLN。如果您已经知道要处理的确切结构,那么最好使用 XML 数据绑定向导中自动创建的包装类。生成的代码通常几乎不可读,但您的其余代码变得更加清晰,所有无聊的创建 XML 文件并将其填充到整洁的 Delphi 结构和集合中并将它们写回的繁琐工作都将为您完成。不知何故,巫师本身仍然有点 1998 年的感觉,但它仍然很有用,尤其是对于大型结构。如果它们发生变化,只需重新生成包装类..
    • +1。请参阅我对有关向导课程的原始问题的评论。我以前使用过带有 .xsd 文件的向导,但从来没有在 xml 本身上生成类。我今天学到了一些我认为我已经知道的新东西 - 谢谢! :)
    • 等等。再次,请参阅我对原始问题的评论。该向导在 D7 中不可用(至少在 Pro SKU 中)。它可能在更高的 SKU 中可用,但 Pro 是我安装的唯一一个(在 VM 中,用于支持使用旧代码但不会升级的客户端)。
    • 数据绑定向导从未出现在 Pro SKU 中。
    【解决方案3】:

    我非常喜欢使用 SimDesign 的 NativeXML。它有不错的文档并且是开源的。 http://www.simdesign.nl/nativexml.html

    【讨论】:

    • 要安装它,您只需将您从 SimDesign 下载的文件解压缩到一个文件夹中,将“nativexml”和“general”文件夹添加到您的库路径,并将 NativeXML 添加到您的 uses 子句中。
    • 哎呀,忘了如果您使用的是 XE2,您可能需要更新 simdesign.inc 文件。我很确定它已经在 SVN 中更新了。 simdesign.nl/forum/viewtopic.php?f=2&t=2097
    【解决方案4】:

    对于 TXmlDocument,Msxml 是内置在 D7 中的(或者我使用的 D6,大致相同)。

    还有一个旧版本的 Dieter Köhler 的内置 XDOM,或者您可以从 www.philo.de/xml/ 下载他更新的 ADOM(使用来自 github.com/Midiar/adomxmldom 的 IDomNode 包装器)。这些是在 Pascal 中实现的 - 非常适合调试。 ADOM 为您提供 XPath 功能。

    编辑:Msxml 也有 XPath(以及 XSLT)。

    【讨论】:

    • 是的,我正在尝试使用内置的 delphi,但它现在似乎无缘无故丢失了一段子数据?
    • TXMLDocument 默认使用 MsXML,但您可以使用 DOMVendor 属性指定另一个解析器。例如。在 D7 中,它还提供 XercesXML 和 OpenXML。
    【解决方案5】:

    我确实解决了这个问题并使用了 Delphi7 内置的 XML 对象。 并且适用于多人。

    这比我最初想象的要困难得多。

    正如我在上面的结构中发现的那样,如果您声明身体状况一切都很好,但如果暗示病情,例如您患有高血压,因此您可能提高了胆固醇(拼写!),那么接下来的问题不在main 声明的条件分支,但在条件下。

    下面的代码确实可以解决这个问题 - 有很大一部分重复引用但我希望它可以工作而不是看起来很漂亮..

    我必须承认,我对 XML 的了解比我想的要多……而且非常感谢 :-) 提供的所有帮助 - 大量阅读堆栈溢出和一些谷歌搜索,我现在有了结果!

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多