11

我正在尝试编写一个针对特定 SPList 执行的 CAML 查询,范围为特定文件夹,从该点递归,并返回所有 ListItems(符合条件)和文件夹。

这是查询的代码,看起来应该可以工作(为便于阅读而格式化):

SPQuery query = new SPQuery();
query.Query = "
<Where>
    <Or>
        <Contains>
            <FieldRef Name=\"FileRef\" />
            <Value Type=\"Text\">foo</Value>
        </Contains>
        <Eq>
            <FieldRef Name=\"FSObjType\" />
            <Value Type=\"Lookup\">1</Value>
        </Eq>
    </Or>
</Where>";

query.ViewFields = "
<FieldRef Name=\"CustomField1\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField2\" Nullable=\"TRUE\" />
<FieldRef Name=\"CustomField3\" Nullable=\"TRUE\" />
";

query.RowLimit = 500;
query.ViewAttributes = "Scope=\"RecursiveAll\"";
query.Folder = startingFolder;
DataTable dt = myList.GetItems(query).GetDataTable();

所以 - 这只会返回 ListItems - 没有文件夹。

如果我从查询中删除其他条件,只留下FSObjType=1,我会收到 COM 异常“无法完成此操作。请重试。”

如果我然后删除 ViewFields,只留下Scope=RecursiveAlland FSObjType=1,我会得到一个空的结果集。

4

7 回答 7

14

Everyone is close, but not quite right.

using (SPSite site = new SPSite("http://server/site"))
{
  SPWeb web = site.RootWeb; // See disposal guidance http://blogs.msdn.com/b/rogerla/archive/2008/10/04/updated-spsite-rootweb-dispose-guidance.aspx

  SPQuery query = new SPQuery();
  query.Query = @"
          <Where>
            <BeginsWith>
              <FieldRef Name='ContentTypeId' />
              <Value Type='ContentTypeId'>0x0120</Value>
            </BeginsWith>
          </Where>";
  query.ViewAttributes = "Scope='RecursiveAll'";
  SPList list = web.Lists[listId];
  SPListItemCollection items = list.GetItems(query);
  // Do stuff with your folders
}

First of all, using this FieldRef is wrong:

<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value>

because the folder content type can be inherited. Therefore, you need to compare against the content type ID, like this:

<Where>
  <BeginsWith>
    <FieldRef Name='ContentTypeId' />
    <Value Type='ContentTypeId'>0x0120</Value>
  </BeginsWith>
</Where>

And then, set the view attribute Scope to RecursiveAll

<View Scope='RecursiveAll'>...</View>

That should return any item whose content type inherits from Folder (0x0120)

于 2011-12-19T20:35:42.627 回答
5

我没有要测试的开发图像,所以我可能需要稍后修改它;但我想你可以试试

query.ViewAttributes = "Scope=\"Recursive\""; 

检索项目将允许您用于SPUtility.GetUrlDirectory(url)获取给定项目的文件夹路径,并从那里解析文件夹层次结构。

于 2009-10-13T01:19:11.653 回答
5

您可以尝试将您的 caml 查询基于文件夹内容类型,

<FieldRef Name='ContentType' /><Value Type='Text'>Folder</Value>

同时保持

Query.ViewAttributes = "Scope=\"RecursiveAll\""; 
于 2009-11-03T13:31:49.130 回答
3

我已经解决了这个问题:

<QueryOptions>
<IncludeAttachmentUrls>True</IncludeAttachmentUrls>
<Folder/> </QueryOptions>

作为查询选项

我在堆栈溢出时发现了我的问题:

如何通过使用 web 服务的共享点列表递归迭代?

于 2009-11-10T11:11:03.887 回答
1

如果我从查询中删除其他条件,只保留 FSObjType=1,我会收到 COM 异常“无法完成此操作。请重试。”

执行此操作时是否删除了<Or>标签?如果不是,它将无法正确运行。

无论如何,这并不能解决您的问题。您是否尝试过将查询留空?它会返回任何东西吗?

我一直在做类似的事情,也遇到了一个问题,也许它有点相关。

于 2009-11-01T00:34:23.757 回答
1

这似乎仍然是 SP 2010 中的一个问题。以下是适用于 2007 年或 2010 年的解决方法代码,基于使用 Web 服务的MSDN 论坛帖子

private static SPListItem RecurseIntoFolders(SPList list, SPFolder parentFolder, string fileReference)
{
    var query = new SPQuery
    {
        Query = "<Where>" +
                "<Eq><FieldRef Name='FSObjType'/><Value Type='Lookup'>1</Value></Eq>" +
                "</Where>",
        ViewFields = String.Format("<FieldRef Name='{0}' />", FileReferenceInternalFieldName),
        ViewAttributes = "Scope='RecursiveAll'",
        Folder = parentFolder
    };

    var items = list.GetItems(query);
    if (items.Count == 0)
        return null;

    foreach (SPListItem item in items)
    {
        parentFolder = item.Folder;

        // TODO: Any other checking that this is the item we want

        return item;
    }
    return RecurseIntoFolders(list, parentFolder, fileReference);
}
于 2011-07-07T07:28:59.823 回答
0
static string GetParentFolder(SPListItem itemToFind, SPFolder folder)  
    { 
        SPQuery query = new SPQuery(); 
       // query.Query =  "<OrderBy><FieldRef Name='Title'/></OrderBy>";
        query.Query = "<Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"Integer\">"+ itemToFind.ID +"</Value></Eq></Where>";
        query.Folder = folder;
        query.ViewAttributes = "Scope=\"Recursive\"";
        SPListItemCollection items = itemToFind.ParentList.GetItems(query);
        int intpartentFolderID=0 ;
        if (items.Count > 0)
        {
        foreach (SPListItem item in items) 
        {

            SPFile f = item.Web.GetFile(item.Url);

            string test11 = f.ParentFolder.Name;
            intpartentFolderID = f.ParentFolder.Item.ID;

            //string test1 = item.File.ParentFolder.Name;

             return (intpartentFolderID.ToString()); 

         }
        }
        return (intpartentFolderID.ToString());     
    }  
于 2015-01-07T14:35:19.017 回答