1

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>
JakeSays
  • 2,048
  • 8
  • 29
  • 43

3 Answers3

4

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.

Community
  • 1
  • 1
Mason Wheeler
  • 82,511
  • 50
  • 270
  • 477
  • i tried a whole series of different RootNode.ChildNodes[x].ChildNodes[y].attributes[z] kinda statements and had no luck :( – JakeSays Nov 27 '13 at 01:10
  • @sholmes: Try the xpath route. If that doesn't work, try "printf debugging": inside your for loops, put a call to `OutputDebugString` (in the `Windows` unit) to get the names of the nodes. That'll give you a good way to visualize what's going on. You're probably just missing a step somewhere. :) – Mason Wheeler Nov 27 '13 at 01:18
  • Can you point me to a reference on how those item tags work, When I google search, of course all my returns are about '<" and "/>" :) – JakeSays Nov 27 '13 at 01:20
  • I dont use printf debugging, but i have a method i do use and I have tried that. You can't debug the nested for loops if you dont know how nested the childnodes are. – JakeSays Nov 27 '13 at 01:29
0

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

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

JakeSays
  • 2,048
  • 8
  • 29
  • 43
  • If you have the schema, you could use "XML DataBinding" wizard too. – Agustin Seifert Nov 27 '13 at 02:06
  • @sholmes That's exactly what Mason's answer tells you...you should accept it instead of adding your own answer. – jpfollenius Nov 27 '13 at 11:12
  • Sorry, I don't see anywhere in his answer showing what I have as an answer,. I clearly stated that i tried all those options , with the following statement "i tried a whole series of different RootNode.ChildNodes[x].ChildNodes[y].attributes[z] kinda statements and had no luck" - He could have clearly helped me out with the line i have provided. It turns out, I was attempting to use attributes instead of AttributeNodes. Mason wanted me to use "nested loops" or "xpath query" when i could clearly be done in one line. – JakeSays Nov 27 '13 at 15:51
  • I gave him an upvote, that should count for something. I am not interested in points my self, only answers. I think my answer will help others in the near future. Had I been as vague with my question as he was with his answer, I would have been attacked from all directions with negatives and comments about being more specific. So, why can't someone like I expect that as an answer from experts? – JakeSays Nov 27 '13 at 15:53
  • @sholmes: No reason to be offended. Your solution differs from the original code only by adding another call to `ChildNodes` - and that is exactly what Mason said. – jpfollenius Nov 28 '13 at 17:23
0

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;
Ken White
  • 123,280
  • 14
  • 225
  • 444