May 26 2010

Filtering XML output of SPListItemCollection using Linq to XML

Category: SharePoint, TechnologyAdam Toth @ 1:57 pm

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()

Tags: , , , ,

4 Responses to “Filtering XML output of SPListItemCollection using Linq to XML”

  1. 3m stock price says:

    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!

  2. 3m stock price says:

    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!

  3. Jon Fulwiler says:

    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!!

  4. Lilli says:

    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.

Leave a Reply