May 26 2010
Filtering XML output of SPListItemCollection using Linq to XML
I’ve been writing a slurry of code to return list item XML so that it can be parsed and consumed by AJAX components on the client side. Since Lists.asmx does not work in anonymous access scenarios, I’ve been creating many proxy .ashx Http Handlers installed in the LAYOUTS directory, to query via the object model and return the XML of the list items, using the .Xml property of a SPListItemCollection.
I had one particular scenario where I couldn’t pre-filter the items in the collection with an SPQuery object (too complicated a query for CAML), so I needed a way to filter the SPListItemCollection afterwards using C#, before returning the XML.
The SPListItemCollection offers the .Delete() and .DeleteItemById() methods, however they will commit the deletion back to SharePoint. I wanted to simply remove some items from the in-memory collection, not delete the items from the server. There was no way that I could see to remove items from an SPListItemCollection in memory only.
I looked into sub-classing or extending the SPListItemCollection class, but there is no public constructor in the base class, and no way to get at the logic behind the .Xml property without nasty reflection.
I ultimately ended up resorting to using Linq to XML to delete the rows directly from the returned XML, and then adjusted the ItemCount accordingly.
Here’s the code:
// Get the list items from a list
SPListItemCollection items = myList.GetItems(mySPQuery);
// Get the xml of the list items
itemXml = surveyItems.Xml;
XNamespace z = "#RowsetSchema";
XDocument xdoc = XDocument.Parse(itemXml);
IEnumerable<XElement> rows = xdoc.Root.Descendants(z + "row");
List<XElement> rowsToDelete = new List<XElement>();
foreach (XElement row in rows)
{
// Here is where you can test for a condition, and decide to remove a row
if (row.Attribute("ows_Title").Value.Contains("Some string to filter on"))
{
rowsToDelete.Add(row);
}
}
while (rowsToDelete.Count > 0)
{
// Update the parent row count
int rowCount = Convert.ToInt32(rowsToDelete[0].Parent.Attribute("ItemCount").Value);
rowsToDelete[0].Parent.Attribute("ItemCount").Value = (rowCount - 1).ToString();
rowsToDelete[0].Remove();
rowsToDelete.RemoveAt(0);
}
// Get the newly filtered xml
itemXml = xdoc.ToString()








January 27th, 2012 at 2:24 am
The very core of your writing appears nice and works very well with me. Throughout the sentences you managed to make me a believer. I however need more information and would rather have you to create more as soon as convenient with you. In the event that you actually accomplish that, I would surely be amazed. I will come back soon to take a look at your updates!
January 27th, 2012 at 3:07 am
The core of your writing appears neat and works properly with me personally. Throughout the writing you actually were able to make me a believer. I still need more information and would like you to write more as soon as convenient with you. When you actually accomplish that, I would certainly end up being amazed. I may come back from time to time to review your updates!
January 28th, 2012 at 7:52 pm
There’s certainly nothing I get pleasure from more compared to visiting this blog each morning just after work. Thank you for all the wonderful posts!!
February 2nd, 2012 at 7:05 pm
This web page might be a walk-through like the data you wanted concerning this and didn’t know who need to have to. Glimpse here, and you’ll certainly discover it.