如何使用循环创建 CAML 查询
How to use a loop to create a CAML query
我希望 CAML 查询看起来像:
<Where>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 3</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 4</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 5</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 6</Value>
</Eq>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 7</Value>
</Eq>
</Or>
</Or>
</Or>
</Or>
</Or>
</Or>
</Where>
到目前为止我尝试了什么:
string sC = "<Where>";
int i = myList.Count - 1;
for (int iL = 0; iL < myList.Count; iL++) //for each person add an OR and the person and then another opening OR?
{
while (i >= 0)
{
sC += "<Or>";
}
sC += "<Eq><FieldRef Name='ename_090' /><Value Type='Text'>" + myList[iL] + "</Value></Eq>";
while (i >= 0)
{
sC += "<Or>";
}
i--;
}
if (myList.Count > 1)
{
sC += "</Or>";
}
sC += "</Where>";
我只是不知道如何使用 for 循环来实现上述目标。
for
循环 内部 的结束 Or
标记是 <Or>
而不是 </Or>
。
首先编写一个方法来为列表中的项目构造 Eq
元素:
public static string TextEquals(string column, string value)
{
return string.Format(
"<Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq>",
column, value);
}
接下来编写一个方法将两个元素包装在一个 Or
元素中:
public static string WrapInOr(string first, string second)
{
return string.Format("<Or>{0}{1}</Or>", first, second);
}
现在我们有了这个,我们可以获取列表中的项目,为每个项目创建相等元素,然后使用 Or
元素聚合它们:
var caml = myList.Select(person => TextEquals("ename_090", person))
.Aggregate((a,b) => WrapInOr(a, b));
输出:
<Or>
<Or>
<Or>
<Or>
<Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 1</Value>
</Eq>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 2</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 3</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 4</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 5</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 6</Value>
</Eq>
</Or>
以下是使用递归执行此操作的方法。
List<string> myList = new List<string>
{
"Person 1",
"Person 2",
"Person 3"
};
Func<string,string> Value = x => string.Format("<Value Type = 'Text'>{0}</Value>",x); // Generate Value
Func<string, string> Eq = x => string.Format("<Eq><FieldRef Name = 'ename_090'/>{0}</Eq>", x); // Generate Eq.
Func<string, int, string> Or = null;
Or = (x, i) => string.Format("<Or>{0}{1}</Or>", x,
i < myList.Count - 2
? Or(Eq(Value(myList[i++])), i)
: i == myList.Count - 2 ? Or(Eq(Value(myList[i++])) + Eq(Value(myList[i])), i) : ""); // Or with recursion call
string sC;
if(myList.Count == 2) // a bit different when length is 2.
{
sC = string.Format("<Where>{0}</Where>", Or(Eq(Value(myList[0])) + Eq(Value(myList[1])), 2));
}
else
{
sC = string.Format("<Where>{0}</Where>", Or(Eq(Value(myList[0])), 1)); // start generating
}
你有三种方法。 Value
取人名。例如:myList[0]
、myList[1]
、等等...
<Value Type='Text'>Person 0</Value>
Eq
显然是格式化字符串。因此,当您执行 Eq(Value(myList[0])
时,您将得到一个 Eq,例如变为
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 0</Value>
</Eq>
那么你有Or
。但它也有一个对自身的调用,称为递归。
所以当你 Or(Eq(Value(myList[0]))
字符串变成
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
{1}
<Or>
{1}
部分将调用自身继续生成,直到列表的最后一个元素。
更新: 根据 Servy 的建议,聚合在这里很有用。
Func<string, string> Value = x => string.Format("<Value Type = 'Text'>{0}</Value>", x); // Generate Value
Func<string, string> Eq = x => string.Format("<Eq><FieldRef Name = 'ename_090'/>{0}</Eq>", x); // Generate Eq.
Func<string, string> Or = x => string.Format("<Or>{0}{{0}}</Or>", x);
int i = 0;
string sC = myList.Skip(1).Aggregate(Or(Eq(Value(myList[0]))), (seed, cur) =>
{
if (i++ < myList.Count - 2)
{
return string.Format(seed, Or(Eq(Value(cur))));
}
return string.Format(seed, Eq(Value(cur)));
});
sC = string.Format("<Where>{0}</Where>", sC);
我希望 CAML 查询看起来像:
<Where>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 3</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 4</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 5</Value>
</Eq>
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 6</Value>
</Eq>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 7</Value>
</Eq>
</Or>
</Or>
</Or>
</Or>
</Or>
</Or>
</Where>
到目前为止我尝试了什么:
string sC = "<Where>";
int i = myList.Count - 1;
for (int iL = 0; iL < myList.Count; iL++) //for each person add an OR and the person and then another opening OR?
{
while (i >= 0)
{
sC += "<Or>";
}
sC += "<Eq><FieldRef Name='ename_090' /><Value Type='Text'>" + myList[iL] + "</Value></Eq>";
while (i >= 0)
{
sC += "<Or>";
}
i--;
}
if (myList.Count > 1)
{
sC += "</Or>";
}
sC += "</Where>";
我只是不知道如何使用 for 循环来实现上述目标。
for
循环 内部 的结束 Or
标记是 <Or>
而不是 </Or>
。
首先编写一个方法来为列表中的项目构造 Eq
元素:
public static string TextEquals(string column, string value)
{
return string.Format(
"<Eq><FieldRef Name='{0}' /><Value Type='Text'>{1}</Value></Eq>",
column, value);
}
接下来编写一个方法将两个元素包装在一个 Or
元素中:
public static string WrapInOr(string first, string second)
{
return string.Format("<Or>{0}{1}</Or>", first, second);
}
现在我们有了这个,我们可以获取列表中的项目,为每个项目创建相等元素,然后使用 Or
元素聚合它们:
var caml = myList.Select(person => TextEquals("ename_090", person))
.Aggregate((a,b) => WrapInOr(a, b));
输出:
<Or>
<Or>
<Or>
<Or>
<Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 1</Value>
</Eq>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 2</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 3</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 4</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 5</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="enam_090" />
<Value Type="Text">Person 6</Value>
</Eq>
</Or>
以下是使用递归执行此操作的方法。
List<string> myList = new List<string>
{
"Person 1",
"Person 2",
"Person 3"
};
Func<string,string> Value = x => string.Format("<Value Type = 'Text'>{0}</Value>",x); // Generate Value
Func<string, string> Eq = x => string.Format("<Eq><FieldRef Name = 'ename_090'/>{0}</Eq>", x); // Generate Eq.
Func<string, int, string> Or = null;
Or = (x, i) => string.Format("<Or>{0}{1}</Or>", x,
i < myList.Count - 2
? Or(Eq(Value(myList[i++])), i)
: i == myList.Count - 2 ? Or(Eq(Value(myList[i++])) + Eq(Value(myList[i])), i) : ""); // Or with recursion call
string sC;
if(myList.Count == 2) // a bit different when length is 2.
{
sC = string.Format("<Where>{0}</Where>", Or(Eq(Value(myList[0])) + Eq(Value(myList[1])), 2));
}
else
{
sC = string.Format("<Where>{0}</Where>", Or(Eq(Value(myList[0])), 1)); // start generating
}
你有三种方法。 Value
取人名。例如:myList[0]
、myList[1]
、等等...
<Value Type='Text'>Person 0</Value>
Eq
显然是格式化字符串。因此,当您执行 Eq(Value(myList[0])
时,您将得到一个 Eq,例如变为
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 0</Value>
</Eq>
那么你有Or
。但它也有一个对自身的调用,称为递归。
所以当你 Or(Eq(Value(myList[0]))
字符串变成
<Or>
<Eq>
<FieldRef Name='ename_090' />
<Value Type='Text'>Person 1</Value>
</Eq>
{1}
<Or>
{1}
部分将调用自身继续生成,直到列表的最后一个元素。
更新: 根据 Servy 的建议,聚合在这里很有用。
Func<string, string> Value = x => string.Format("<Value Type = 'Text'>{0}</Value>", x); // Generate Value
Func<string, string> Eq = x => string.Format("<Eq><FieldRef Name = 'ename_090'/>{0}</Eq>", x); // Generate Eq.
Func<string, string> Or = x => string.Format("<Or>{0}{{0}}</Or>", x);
int i = 0;
string sC = myList.Skip(1).Aggregate(Or(Eq(Value(myList[0]))), (seed, cur) =>
{
if (i++ < myList.Count - 2)
{
return string.Format(seed, Or(Eq(Value(cur))));
}
return string.Format(seed, Eq(Value(cur)));
});
sC = string.Format("<Where>{0}</Where>", sC);