0

I'm looking at the example below, and I wonder, after I'm done reading all the image nodes, how do I get back reading the last_modified_at node from parent element? (See my comments in last few lines of code)

public class StackOverflow_6473251
{
    public static void Test()
    {
        string xml = @"
           <movies>
             <movie>
               <score>8.582207</score>
               <popularity>3</popularity>
               <translated>true</translated>
               <adult>false</adult>
               <language>en</language>
               <original_name>Transformers</original_name>
               <name>Transformers</name>
               <alternative_name>The Transformers</alternative_name>
               <type>movie</type>
               <id>1858</id>
               <imdb_id>tt0418279</imdb_id>
               <url>http://www.themoviedb.org/movie/1858</url>
               <votes>28</votes>
               <rating>7.2</rating>
               <certification>PG-13</certification>
               <overview>The Earth is caught in the middle of an intergalactic war /overview>
               <released>2007-07-04</released>
               <images>
                    <image type=""poster"" url=""http://hwcdn.themoviedb.org/posters/304/4bc91347017a3c57fe007304/transformers-original.jpg"" size=""original"" id=""4bc91347017a3c57fe007304""/>
                    <image type=""poster"" url=""http://hwcdn.themoviedb.org/posters/304/4bc91347017a3c57fe007304/transformers-mid.jpg"" size=""mid"" id=""4bc91347017a3c57fe007304""/>
                    <image type=""poster"" url=""http://hwcdn.themoviedb.org/posters/304/4bc91347017a3c57fe007304/transformers-cover.jpg"" size=""cover"" id=""4bc91347017a3c57fe007304""/>
                    <image type=""poster"" url=""http://hwcdn.themoviedb.org/posters/304/4bc91347017a3c57fe007304/transformers-thumb.jpg"" size=""thumb"" id=""4bc91347017a3c57fe007304""/>
                    <image type=""backdrop"" url=""http://hwcdn.themoviedb.org/backdrops/2ce/4bc91339017a3c57fe0072ce/transformers-original.jpg"" size=""original"" id=""4bc9133s9017a3c57fe0072ce""/>
                    <image type=""backdrop"" url=""http://hwcdn.themoviedb.org/backdrops/2ce/4bc91339017a3c57fe0072ce/transformers-poster.jpg"" size=""poster"" id=""4bc91339017a3c57fe0072ce""/>
                    <image type=""backdrop"" url=""http://hwcdn.themoviedb.org/backdrops/2ce/4bc91339017a3c57fe0072ce/transformers-thumb.jpg"" size=""thumb"" id=""4bc91339017a3c57fe0072ce""/>
               </images>
             <last_modified_at>2010-04-26 03:26:14</last_modified_at>
       </movie>
     </movies>";
        XmlReader r = XmlReader.Create(new StringReader(xml));
        r.ReadToFollowing("original_name");
        string title = r.ReadElementContentAsString("original_name", r.NamespaceURI);
        r.ReadToFollowing("images");
        int imageCount = 0;
        if (r.ReadToDescendant("image"))
        {
            do
            {
                Console.WriteLine("Image {0}", ++imageCount);
                Console.WriteLine("  Type: {0}", r.GetAttribute("type"));
                Console.WriteLine("  URL: {0}", r.GetAttribute("url"));
                Console.WriteLine("  Size: {0}", r.GetAttribute("size"));
                Console.WriteLine("  ID: {0}", r.GetAttribute("id"));
            } while (r.ReadToNextSibling("image"));
        }
        //read last_modified_at
        //reader.Name evaluates to 'images' at execution time
        //reader.NodeType evaluates to 'EndElement' at execution time
    }
}

UPDATE

In a similar scenario, I'm trying to achieve the same result successfully accomplished by the answers below unsuccessfully, and fails at the highlighted line (41) by returning false.
The problem is going from the last abbr to intervals. And here is where I can't see the difference from the example presented above.

Update Here is a complete example.

Community
  • 1
  • 1
Shimmy Weitzhandler
  • 101,809
  • 122
  • 424
  • 632

3 Answers3

1

You can't. From the documentation:

"Represents a reader that provides fast, noncached, forward-only access to XML data."

You could read from the start again.

Or, since the data is very small, you could use an XmlDocument which allows greater flexibility.

Steve Wellens
  • 20,506
  • 2
  • 28
  • 69
1

As last_modified_at follows the images you can do it as you did it some lines up:

r.ReadToFollowing("last_modified_at");
string lastModified = r.ReadElementContentAsString("last_modified_at", r.NamespaceURI);
Fratyx
  • 5,717
  • 1
  • 12
  • 22
  • [Here](http://pastebin.com/ZetsSmmL)'s code that have same example, but fails! on the highlighted line, `reader.Name` evaluates to `ChordType` and `reader.NodeType` is `EndElement`. Why is that? – Shimmy Weitzhandler Oct 10 '14 at 04:58
  • @Shimmy Why are you using pastebin? that code should have been your question. – weston Oct 10 '14 at 05:09
  • 1
    As I can see it the code should crash at the line `if (reader.Name != "abbreviations")` already because you do not read the `abbreviations` tag before. – Fratyx Oct 10 '14 at 05:18
  • @Shimmy I've tested this answer it absolutely works and they're absolutely correct about where the code crashes. Make a Short Self Contained Correct Example. – weston Oct 10 '14 at 05:30
  • @Fratyx, I don't understand, why should I be reading the `abbreviations` before? – Shimmy Weitzhandler Oct 10 '14 at 05:58
  • @weston, you're right. I initially started the question by posting the similar example. Can you notice the difference between the code in my question (which works according to Fratyx's answer), and the code in pastebin that fails? – Shimmy Weitzhandler Oct 10 '14 at 06:00
  • @Shimmy At line 23 of your code the reader "stands before" the `abbreviations` tag. First the reader has to read this element (`reader.Read()`) then the `Name` of the reader will be "abbreviations". – Fratyx Oct 10 '14 at 06:08
  • -1 The `Reader` pattern is a forward reading pattern. There is no guarantee that the underlying data structure can be read backwards (NetworkStream for instance). – Aron Oct 10 '14 at 06:12
  • @Aron, the structure and order of the elements in the XML file of the pastebin is guaranteed to be the same. After the `abbreviations` element, I need the reader to move to the `intervals`. @Fratyx, the problem is at line 40, the `abbreviations` part is read just fine. – Shimmy Weitzhandler Oct 10 '14 at 10:13
  • I'm sorry but after fixing 'my' problem in line 23 I don't get a problem in line 40. – Fratyx Oct 10 '14 at 10:22
  • Ok. [Here](http://pastebin.com/Un0B9i1P)'s a complete reproduction. I've tried replacing the condition on line 59 with: `!reader.Read()`, `reader.Name != "intervals"`, and `!reader.ReadToFollowing("intervals")`, they all evaluate to false. – Shimmy Weitzhandler Oct 10 '14 at 11:56
  • 1
    Replace lines 54-56 by `while(reader.Name == "abbr") Trace.WriteLine(string.Format("Abbreviation {0} - Category: {1}, Abbr: {2}", ++i, reader.GetAttribute("category"), reader.ReadElementContentAsString()));` ReadElementContentAsString() moves to the next sibling and ReadToNextSibling does it again so you skip each second entry by your solution. – Fratyx Oct 10 '14 at 12:23
  • Yep. A few tweaks done but this was the catch. Thanks for you effort and patience @Fratyx. – Shimmy Weitzhandler Oct 10 '14 at 12:45
  • You're welcome. Just as advice: Use XmlDocument or even better XDocument for reading XML. XmlReader maybe suitable for very large XML documents but the alternatives are much easier to handle. – Fratyx Oct 10 '14 at 12:54
  • I'm using the `XmlReader`, because it saves performance as it's *forward-only*, as [Steve mentions](http://stackoverflow.com/a/26291962/75500). I'll have to iterate on a large amount of nodes at program startup and choose to optimize wherever I can. `XDocument`, although way more flexible and convenient, iterates over from the beginning of the node for each query. – Shimmy Weitzhandler Oct 11 '14 at 16:47
0

In your pastebin example, instead of if (reader.Name != "abbreviations") do:

if (!reader.ReadToFollowing("abbreviations"))

It fails because you are not on abbreviations tag yet.

The corresponding working code in the question is:

r.ReadToFollowing("images");

In fact there are no reader.Name != tests.

weston
  • 54,145
  • 21
  • 145
  • 203