Search code examples
delphixpathdelphi-xedelphi-xe7

Get attribute value from XML


Anyone can help me how can I get attribute values from the xml?

My XML looks like...

<?xml version="1.0" encoding="iso-8859-2"?>
<root>
 <class classtype="TSampleClass" reference_id="1">
 <class name="FList" classtype="TList&lt;class.TKtgSampleClass;" reference_id="2">
  <dynarray name="FItems" count="2" reference_id="3">
    <class index="0" classtype="TRecord" reference_id="4">
      <member name="FID" type="Integer">1</member>
      <member name="FName" type="string">Name1</member>
      <member name="FComment" type="string">comment1</member>
    </class>
    <class index="1" classtype="TRecord" reference_id="5">
      <member name="FID" type="Integer">0</member>
      <member name="FName" type="string">Name2</member>
      <member name="FComment" type="string">comment2</member>
    </class>
  </dynarray>
  <member name="FCount" type="Integer">2</member>
  <class name="FArrayManager" classtype="TMoveArrayManager&lt;class.TKtgSampleClass;" reference_id="6"/>
 </class>
 <member name="FNextID" type="Integer">2</member>
 </class>
 </root>

I tried with this:

procedure GetValues;
var
  C: Integer;
  vXMLDOC: IXMLDOMDocument;
  vNodes : IXMLDOMNodeList;
  vNode : IXMLDOMNode;
  s: string;
begin
  vXMLDOC := CoDOMDocument.Create;
  vXMLDOC.load(c_FileName);

  vNodes := vXMLDOC.selectNodes('//dynarray/class');

for C := 0 to vNodes.length -1 do
begin
  showmessage(vNodes.item[C].text);
//    s := vNodes.item[C].attributes.getNamedItem('FName').text;
 end;
end;

vNodes.item[C].text gives all the values, but I need the values one by one (FID, FName...)

Thanks!


Solution

  • If, as you now say, you want to get the attributes of the <member> nodes, one way to do it is like so:

    procedure TForm1.GetValues;
    var
      C, i: Integer;
      vXMLDOC: IXMLDOMDocument;
      vNodes : IXMLDOMNodeList;
      vNode : IXMLDOMNode;
      vAttr : IXMLDomNode;
      s: string;
    begin
      vXMLDOC := CoDOMDocument.Create;
      vXMLDOC.loadXML(Memo1.Lines.Text);
    
      vNodes := vXMLDOC.selectNodes('/root/class/class/dynarray/class/*');  // will find ALL nodes
      //  below the final <class> one
    
      //  OR  vNodes := vXMLDOC.selectNodes('/root/class/class/dynarray/class/member');  // will
      //  find only the <member> nodes below the final <class> one
    
      for C := 0 to vNodes.length -1 do
      begin
        vNode := vNodes.item[C];
        Memo2.Lines.Add('NodeText: '+ vNode.text);
        for i := 0 to vNode.attributes.length - 1 do begin
          vAttr := vNode.attributes.item[i];
          s := Format('attr name: %s, attr value: %s', [vAttr.nodeName, vAttr.nodeValue]);
          Memo2.Lines.Add(s);
        end;
        //  instead of the `for i:=` loop, you could do something like this
        //  vAttr := vNode.attributes.getNamedItem('name');
        //  s := Format('attr name: %s, attr value: %s', [vAttr.nodeName, vAttr.nodeValue]);
        //  Memo2.Lines.Add(s);
    
      end;
    end;