JakeSays
JakeSays

Reputation: 2068

Extracting unknown values from XML nodes

Can someone help me with getting the "Test Project n" string values from each of these items in <a n="Formatted Name" v="Test Project 1"/>

These do not seem to appear to be attributes. What are they and how do I get the text i need?

<?xml version="1.0" encoding="utf-8" ?>
<items>
<item Id="814135481" Rank="1"><a n="Formatted Name" v="Test Project 1"/></item>
<item Id="814135882" Rank="2"><a n="Formatted Name" v="Test Project 2"/></item>
<item Id="814135908" Rank="3"><a n="Formatted Name" v="Test Project 3"/></item>
</items>

 RootNode := XMLDoc.DocumentElement;
  for I := 0 to RootNode.ChildNodes.Count-1 do
  begin
   //
  end;

RootNode.ChildNodes[I].AttributeNodes[n]

will give me the list of attributes on the item, but I dont know how to extract these values

<a n="Formatted Name" v="Test Project 1"/>

XML for understanding ANSWER:

<?xml version="1.0" encoding="utf-8" ?>
    <items>
      <item Id="814135481" Rank="1">
        <a n="Formatted Name" v="Test Project 1"/>
    </item>
      <item Id="814135882" Rank="2">
        <a n="Formatted Name" v="Test Project 2"/>
    </item>
      <item Id="814135908" Rank="3">
        <a n="Formatted Name" v="Test Project 3"/>
    </item>
    </items>

Upvotes: 1

Views: 282

Answers (3)

Ken White
Ken White

Reputation: 125620

The easiest way is to use IXMLDOMDocument and XPath;

uses
  msxml;

const
  TestXML = '<?xml version="1.0" encoding="utf-8" ?>' +
            '<items><item Id="814135481" Rank="1">' +
            '<a n="Formatted Name" v="Test Project 1"/></item>' +
            '<item Id="814135882" Rank="2">' + 
            '<a n="Formatted Name" v="Test Project 2"/>' + '</item>' +
            '<item Id="814135908" Rank="3">' + 
            '<a n="Formatted Name" v="Test Project 3"/>' + 
            '</item></items>';

var
  Doc: IXMLDOMDocument;
  NodeList: IXMLDOMNodeList;
  ANode: IXMLDOMNode;
  i: Integer;
begin
  Doc := CoDOMDocument.Create;
  Doc.loadXML(TestXML);

  // Select all of the <a> nodes only 
  NodeList := Doc.selectNodes('//a');

  // Error checking omitted. Should test for `NodeList <> nil` before use here.
  for i := 0 to NodeList.length - 1 do
    // Should really use another node here as an intermediate
    //  step, to make sure that getNamedItem succeeded. Omitted
    //  for brevity 
    Memo1.Lines.Add(Node.attributes.getNamedItem('v').nodeValue);
end;

Upvotes: 0

JakeSays
JakeSays

Reputation: 2068

Turns out it was easier than I thought. I was reading the XML wrong:

RootNode.ChildNodes[I].ChildNodes[0].AttributeNodes[1].Text;

Upvotes: 0

Mason Wheeler
Mason Wheeler

Reputation: 84540

They are attributes on the a tag, but the a tags are children of the item tags, which are children of the items tag. Your for loop will only give you one result, the items node.

You can either process this with nested loops, or you can use an xpath query to get a collection of all the tags that match items/item/a. Then you look at the attributes on those.

Upvotes: 4

Related Questions