在Delphi中解析具有相同名称的元素的XML数据

时间:2013-12-02 19:43:12

标签: delphi dom xml-parsing

我看到有些问题询问如何解析具有相同名称但没有显示迭代方式的标记的XML。  我正在提取格式化的XML

<Documents>
 <a:Document>
  <a:ID>264</a:ID>
  <a:DocumentTitle>Packaged Air-Handling Units</a:DocumentTitle>
 </a:Document>
 <a:Document>
  <a:ID>324</a:ID>
  <a:DocumentTitle>Heater Coil</a:DocumentTitle>
 </a:document>
</Documents>

我必须解析的代码是

Procedure EpicParse( ED : TDOMDocument30; Var ET : EpicTag );
Var
  epicNodeList  : IXMLDOMNodelist;
  I             : Integer;

Begin

  epicNodeList  := ED.DefaultInterface.getElementsByTagName( 'a:ID' );
  ET.id         := epicNodeList.item[ 0 ].text;
end;

这将获得a:ID的第一个实例,但是如何设置for循环从a的一个实例获取信息:然后递增并从下一个获取信息。

2 个答案:

答案 0 :(得分:0)

首先获取Document元素列表:

myList := ED.DefaultInterface.getElementsByTagName( 'a:Document' );

然后遍历此列表元素,以收集ID元素。

答案 1 :(得分:0)

有几种方法可以做你所问的。以下是其中几个示例,它是一个按钮单击事件处理程序,用于填充普通旧TMemo的内容。它使用MSXML,因此它仅适用于Windows。我已经对代码进行了评论,以解释它的作用和原因。

我根据您提供的内容(有点)包含了示例XML,因为您发布的内容无效。 (它包含一个名称空间别名a:,用于未包含的名称空间。此外,XML区分大小写,因此</document>不是<Document>的结束元素,因此XML不会正确解析。)在适应实际代码后,您需要在适当的位置添加命名空间别名。

uses
  msxml;

const
  sXML = '<Documents>'#13 +
         '  <Document>'#13 +
         '    <ID>264</ID>'#13 +
         '    <DocumentTitle>Packaged Air-Handling Units</DocumentTitle>'#13 +
         '  </Document>'#13 +
         '  <Document>'#13 +
         '    <ID>324</ID>'#13 +
         '    <DocumentTitle>Heater Coil</DocumentTitle>'#13 +
         '  </Document>'#13 +
         '</Documents>'#13 ;

procedure TForm1.Button1Click(Sender: TObject);
var
  XMLDoc: IXMLDOMDocument;
  NodeList: IXMLDOMNodeList;
  Node, SubNode: IXMLDOMNode;
  i, j: Integer;
begin
  Memo1.Lines.Clear;
  XMLDoc := CoDOMDocument.Create;
  XMLDoc.loadXML(sXML);

  Memo1.Lines.Add('XPath select');
  Memo1.Lines.Add('============');

  // Select all of the Document elements (and their child nodes)
  NodeList := XMLDoc.selectNodes('/Documents/Document');
  for i := 0 to NodeList.length - 1 do
  begin
    // Get each Document node
    Node := NodeList.item[i];
    // Select the ID node
    SubNode := Node.selectSingleNode('ID');
    Memo1.Lines.Add('ID: ' + SubNode.firstChild.Text);
    // Select the DocumentTitle node
    SubNode := Node.selectSingleNode('DocumentTitle');
    Memo1.Lines.Add('DocumentTitle: ' + SubNode.firstChild.Text);
    Memo1.Lines.Add('');
  end;

  Memo1.Lines.Add('Iteration');
  Memo1.Lines.Add('=========');
  // Still select all Document elements using XPath, slightly different expression.
  // Note we really didn't need to do this, because the reference we had
  // before is still valid. Just included as an example.
  NodeList := XMLDoc.selectNodes('//Document');
  for i := 0 to NodeList.length - 1 do
  begin
    // Get each Document node
    Node := NodeList.item[i];
    // Iterate through it's child nodes (ID and DocumentTitle),
    // outputting both the node name and its text content
    for j := 0 to Node.childNodes.length - 1 do
    begin
      SubNode := Node.childNodes[j];
      Memo1.Lines.Add(SubNode.nodeName + ': ' + SubNode.firstChild.text);
    end;
    Memo1.Lines.Add('');
  end;
end;