views:

202

answers:

1

I have a loaded XDocument that I need to grab all the attributes that equal a certain value and is of a certain element efficiently. My current

IEnumerable<XElement> vm;
if (!cacher2.TryGetValue(name,out vm)) { 
    vm = project.Descendants(XName.Get(name));
    cacher2.Add(name, vm);
}


XElement[] abdl = (vm.Where(a =>  a.Attribute(attribute).Value == ab)).ToArray();

cacher2 is a Dictionary<string,IEnumerable<XElement>> The ToArray is so I can evaluate the expression now. I don't think this causes any real speed concerns. The problem is the Where itself. I am searching through anywhere from 1k to 10k items.

+1  A: 

Do you need to call .ToArray? I'm unclear on why you can't just loop over adding to the dictionary (or call .ToDictionary). However; have you profiled? If there is a bottleneck here, you might try dropping back to XmlReader and treating it as a firehose:

        while (reader.Read())
        {
            if (reader.NodeType == XmlNodeType.Element
                && reader.GetAttribute("attribName") == attribValue)
            {
                /* do something interesting for fun and profit */
            }
        }

With your existing code, though, I would be very tempted to make it:

vm.Where(a =>  (string)a.Attribute(attribute) == ab)

The difference is that by not calling .Value it should work even when the attribute isn't set. Of course if you demand that this attribute is always set then an exception may be acceptable in this case.

Marc Gravell
Do you know of any quick way to convert from my vm = project.Descendants(XName.Get(name)); statement to an XmlReader?I will try that and see if there is a change. I have profiled by the way, that single line of code is the bottleneck for my application. I understand reevaluating my needs, but for now this is the path I am taking.
Dested
The `while(reader.Read())` would be the heart of it. You can use `ReadSubtree` to get a child-reader to read nodes, so perhaps just use `XElement.Load(reader.ReadSubtree())` to get the nodes you care about?
Marc Gravell
I am using someXElement.CreateReader(); to create a new xmlreader every time I need to run this "query". Do you recommend I cache the reader and somehow set it back to the beginning when I'm done? Or should I create them when I need them?
Dested
@Dested - I'm talking about the data-volume where you don't have an `XElement` in the first place. If you've already parsed the xml into a DOM it is too late for such considerations.
Marc Gravell