Reputation: 3091
I am using LINQ to filter the XmlNode returned from Sharepoint WSS3's listService.GetListItems()
method.
This is the XML it returns: http://pastebin.com/mqHcserY
I observed that the last row is different to the others, it does not contain the following attributes.
ows_ContentType
ows_LinkFilenameNoMenu
ows_LinkFilename
ows_BaseName
ows__EditMenuTableStart
So bearing this in mind I filter the results with LINQ:
XmlNode items = listService.GetListItems(listName, string.Empty, query, viewFields, string.Empty, queryOptions, g.ToString());
// Namespace for z: prefix
XNamespace xns = "#RowsetSchema";
XElement root;
using (XmlReader xr = new XmlNodeReader(items)) { root = XElement.Load(xr); }
// This query returns XElements that are Folder types
IEnumerable<XElement> result = from child in root.Descendants(xns + "row")
where child.Attribute("ows_ContentType").Value != null && child.Attribute("ows_ContentType").Value == "Folder"
select child;
foreach (XElement xml in result)
{
//Exception when attempts to loop final XElement
}
However when I iterate through the results I get a NullReferenceException
. In a Foreach loop it will happily iterate through every object until it gets to the last one, then it will throw an exception.
This last object is the one that differs from the other rows (I know this through process of elimination, I saw every other row get looped past) and should have been filtered out of my results as it does not have the "ows_ContentType" attribute.
I changed my LINQ to where child.Attribute("ows_ContentType").Value != null && child.Attribute("ows_ContentType").Value == "Folder"
in attempt to filter anything that would contain a null value but I have the same results.
I have looked at a few samples and I appear to have the correct syntax.
Could someone please explain what is causing this last XElement to return null?
I really don't understand why it would add a null instance to the <IEnumerable<XElement> result
collection.
Upvotes: 3
Views: 1608
Reputation: 51711
The last node doesn't contain an "ows_ContentType" attribute, but your where clause is looking for the value of that missing attribute.
Possibly you need
where child.Attribute("ows_ContentType") != null
&& child.Attribute("ows_ContentType").Value == "Folder"
Upvotes: 0
Reputation: 167571
Note that LINQ2XML simply allows you to use (string)someXElement
and (string)someXAttribute
which will give null if the XElement or XAttribute is null or the Value of the XElement or XAttribute if it exists. That means you code can be shortened to use
IEnumerable<XElement> result = from child in root.Descendants(xns + "row")
where (string)child.Attribute("ows_ContentType") == "Folder"
select child;
Upvotes: 1
Reputation: 2585
Calling the value of a non existing attribute will cause a nullreference because the node simply doesn't exist.
child.Attribute("ows_ContentType").Value
throws an exception by calling the value of the missing element.
use this instead:
child.Attribute("ows_ContentType") != null
implemented:
IEnumerable<XElement> result = from child in root.Descendants(xns + "row")
where child.Attribute("ows_ContentType") != null && child.Attribute("ows_ContentType").Value == "Folder"
select child;
Upvotes: 3
Reputation: 3612
You need to check whether the element is null NOT the value of the element.
child.Attribute("ows_ContentType") != null && child.Attribute("ows_ContentType").Value == "Folder"
Upvotes: 2