2

I have an XML file that can be one-line:

<webshop><item></item><item></item></webshop>

or multiline:

<webshop>
    <item>
    </item>
    <item>
    </item>
</webshop>

or mixed:

<webshop>
    <item></item>
    <item></item>
</webshop>

Each tag also has a short variant like <webshop/> and <item/> where the tag is opened and closed in one pair of < > brackets.

each tag can appaer any amount of times, but the <item></item> or <item/> tag will only appaer inside <webshop> ... </webshop>. Also, the entire xml tag hierarchy is much larger then just these two tags (but I kept it simple for this question), and each tag can have attributes.

I'm trying to parse such an xmlfile using an xmlreader in c#, but I always run into a problem.

If I try:

while(reader.ReadToFollowing("webshop"))
{
    Console.WriteLine("webshop");
    //get attributes of webshop tag and do something...

    while(reader.ReadToFollowing("item"))
    {
         Console.WriteLine("Item");
        //get attributes of item tag and do something...
    }
}

I never get all the data when the xml is singleline, mixed or the tags close themself (<item/> instead of <item></item>). Most of the time, the reader just stops after one instance of <webshop> or <item>

Is there a robust way to parse this xml, even if the exact lining is not known beforehand? I want to loop over all webshops, and for each webshop loop all over items, and then do something with this data.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
user1884155
  • 3,616
  • 4
  • 55
  • 108
  • 5
    You're misusing XmlReader. Use LINQ to XML; it's _far_ easier to use. – SLaks Dec 30 '13 at 15:13
  • What exactly is being misused? Can you give more details about "use Linq to XML"? Any tutorial or reference? – user1884155 Dec 30 '13 at 15:15
  • http://broadcast.oreilly.com/2010/10/understanding-c-simple-linq-to.html, e.g. – bas Dec 30 '13 at 15:16
  • I think perhaps he means that you are "using" `XmlReader`, which is very similar to misuse. Use LINQ to XML instead. – John Saunders Dec 30 '13 at 15:16
  • XmlReader would be for huge documents I see no reason to use it here. LinqToXml is an easy google, XmlDocument class would deal with this as well. You need to put your xml head on though, multi-line is for text documents. – Tony Hopkinson Dec 30 '13 at 15:20
  • http://msdn.microsoft.com/en-us/library/bb387061.aspx – SLaks Dec 30 '13 at 15:24
  • @JohnSaunders: No; I mean misusing; he isn't reading into nested elements correctly. – SLaks Dec 30 '13 at 15:25

2 Answers2

4

Here's a very simple Linq to XML way to read your xml file:

var xml = @"<webshop><item></item><item></item></webshop>";

var reader = XDocument.Parse(xml);

var webshops = from w in reader.Elements("webshop")
                select w;

foreach(var shop in webshops)
{
    var items = from i in shop.Elements("item")
                select i;

    //can now grab any attributes of the items
}

Without more details on the attributes in these elements, I can't provide much more detail in an example, but I think this is enough to show you how it can be done.

If you aren't going to do any filtering and just want all of the webshop elements and then their constituent item subelements, you can simplify what I have above like so:

var webshops = reader.Elements("webshop");

foreach(var shop in webshops)
{
    var items = shop.Elements("item");

    //can now grab any attributes of the items
}

I originally included the more verbose way of structuring the queries in case you wanted to do any filtering or wanted to do something more complex then simply selecting the given elements. This simplified method will produce the same results as my first example.

Sven Grosen
  • 5,616
  • 3
  • 30
  • 52
  • There is never any reason to write `from x in y select x`. – SLaks Dec 30 '13 at 15:25
  • @SLaks I agree, generally, but since the OP has no apparent knowledge of Linq to XML, I thought I'd be overly verbose for demonstration purposes, and his example is sparse enough that I thought I'd keep it in this format so if he did want to do any filtering or other processing, it would be simple to add. – Sven Grosen Dec 30 '13 at 15:26
  • 1
    No; you're just teaching him to write useless code without understanding it. If you give complete code in a situation like this, most users will blindly paste in your code without reading any documentation or understanding what it means. – SLaks Dec 30 '13 at 15:27
  • Fair enough, I am probably a bit naive still about how most OP's use these answers. – Sven Grosen Dec 30 '13 at 15:32
  • 1
    first, I don't think it's necessary to assume anything about my ability to read sql like statements. Secondly, I appreciate code examples far more than comments on how those examples are not optimal. thank you. – user1884155 Dec 30 '13 at 15:32
  • @user1884155: I'm sorry to underestimate you; it's just that I've seen far too many users who do exactly that. (then come right back again with another question about how to make the pasted code do what they want) – SLaks Dec 30 '13 at 15:36
  • 2
    I think your comments would be better if you not only say what's wrong, but also why it is wrong and what a possible solution could be. Of course, I understand (y)our time is costly so I'm grateful for even the smallest amount of info. – user1884155 Dec 30 '13 at 15:41
  • I do accept answers. However, usually I don't get an answer that I can implement. Either because I'm not experienced enough to implement it, or because the answer does not satisfy my specific usecase (possible because I asked the wrong question). In both cases, I don't think accepting an answer is meaningful because I cannot verify it to be the right solution. – user1884155 Dec 30 '13 at 15:50
1

Please take a look at the answer in this stack overflow discussion.

binding xml elements to model in MVC4

Basically, there are many ways to read xml files in you c# code. It all depend on what you are trying to achieve and how flexible it has to be. I personally prefer to XmlSeriealizer as it translate the xml into c# objects. the only downside is that you have to define classes for the xml to translate into.

Community
  • 1
  • 1
Amila
  • 3,711
  • 3
  • 26
  • 42