0

I have the following XML

<Company name="Kinanah Computers">
  <Computer Name="Computer" type="Dell">
      <Accessory type="screen" model="dell"/>
      <Accessory type="mouse" model="dell"/>
      <Accessory type="keyboard" model="dell"/>
  </Computer>
  <Computer Name="Computer" type="HP">
        <Accessory type="screen" model="hp"/>
        <Accessory type="mouse" model="chinese"/>
        <Accessory type="keyboard" model="dell"/>
  </Computer>
  <Computer Name="Computer" type="HP">
        <Accessory type="screen" model="hp"/>
        <Accessory type="mouse" model="chinese"/>
        <Accessory type="keyboard" model="dell"/>
  </Computer>
  <Computer Name="Computer" type="acer">
        <Accessory type="screen" model="acer"/>
        <Accessory type="mouse" model="acer"/>
        <Accessory type="keyboard" model="acer"/>
  </Computer>
</Company>

what I want to do, is to skip the HP computer if its type is HP, can anybode tell me how to do that?

I'm using the following C# code :

var stream = new StringReader(instanceXml/*the xml above*/);
var reader = XmlReader.Create(stream);
var hpCount = 0;
reader.MoveToContent();

while (reader.Read())
{
  if(reader.NodeType == XmlNodeType.Element)
  {
     if(reader.GetAttribute("Name") == "Computer" && reader.GetAttribute("type") == "HP")
     {
        if(hpCount >1)
        {
           reader.Skip();
          continue;
        }
        hpCount++;
     }
  }
}

but the Skip isn't working, next element that got read is

<Accessory type="screen" model="hp"/>

any help of how to skip these lines ? thank you.

Zero
  • 118
  • 3
  • 14
  • Does the `Skip()` line get hit? Could easily be the conditional that's wrong, not the use of Skip(). – Tom W Nov 19 '12 at 10:39
  • I don't know then. The usage of `Skip()` here is the same as the docs describe, so I can't see why it wouldn't work. – Tom W Nov 19 '12 at 10:47

3 Answers3

1

You can easily parse your xml with Linq:

XDocument xdoc = XDocument.Parse(instanceXml);
var query = from c in xdoc.Descendatns("Computer")
            where (string)c.Attribute("type") != "HP"
            select new {
               Name = (string)c.Attribute("Name"),
               Type = (string)c.Attribute("type"),
               Accessories = from a in c.Elements()
                             select new {
                                Type = (string)a.Attribute("type"),
                                Model = (string)a.Attribute("model")
                             }
            };

This will give you collection of strongly-typed anonymous objects, representing computer data with nested collection of accessories.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • actually this won't help since I'm gonna filter according to count, sorry I've updated the code up there , could you please re-check it? – Zero Nov 19 '12 at 10:42
  • @Zero what are you trying to achieve - it's not clear. You want to take only first computer of HP type? – Sergey Berezovskiy Nov 19 '12 at 10:57
  • no I want to get a specific count of HP computers, imagine the XML is too large and you need only 200 HP computers among 1000.. so when the compiler reaches the computer 201 it should be skipped along with its children. thanks a lot for your help. – Zero Nov 19 '12 at 11:20
0

actually this won't help since I'm gonna filter according to count, sorry I've updated the code up there , could you please re-check it?

List<XElement> query = from c in xdoc.Decendants("Computer") // from <Computer> tag or lower
where (string)c.Attribute("type") == "HP" // where <Computer> attribute name is "type" and "type" equals string value "HP"
select c; // return List of matching `<Computer>` XElements

int HpComputers = query.count; // You want to filter by amount of HP computers?

Filter according to count like this?

Amicable
  • 3,115
  • 3
  • 49
  • 77
0

Instead of checking the hpCount > 1, check hpCount > 0

if(hpCount >1)
{
  reader.Skip();
  continue;
 }
andy
  • 5,979
  • 2
  • 27
  • 49