#region Usings
using System.Collections.Generic;
using System.Text;
#endregion
/// <summary>
/// CAML Operations
/// </summary>
public enum CamlOperator
{
Contains,
BeginsWith,
Eq,
Geq,
Leq,
Lt,
Gt,
Neq,
DateRangesOverlap,
IsNotNull,
IsNull
}
/// <summary>
/// CamlBuilder constructs CAML queries. Useful when needing dynamic generated CAML.
/// Written by Tim Wheeler https://codemonkeysoftware.atlassian.net/wiki
/// Version 2 4 24/10/2015
/// </summary>
/// <remarks>
/// bool allWords = true;
/// CamlBuilder builder = new CamlBuilder();
/// builder.Begin(allWords); //Uses an AND query
/// builder.AddViewFields(new string[] {"Company", "Business Phone"});//Or leave empty to return all fields;
/// builder.AddClause(CamlOperator.Contains, "Title", "My Text To Search For");
/// builder.AddOrderBy("Company",true);
/// ...
/// SPQuery query = new SPQuery();
/// query.Query = builder.Query;
/// query.ViewFields = builder.ViewFields;
/// ...
/// Updates:
/// Now contains ViewXml property when using with Client Object Model
/// example:
/// var builder = new CamlBuilder();
/// builder.Begin(true);
/// builder.AddViewField("Title");
/// builder.AddClause(CamlOperator.Eq, Fields.Title, "My Page Title");
/// var query = new CamlQuery();
/// query.ViewXml = builder.ViewXml;
/// </remarks>
public class CamlBuilder
{
#region PrivateQuery VariablesBuilding
private ICollection<string> _camlClauses = new List<string>();string BuildQuery()
{
private Dictionary<string, bool> _orderByFields = new Dictionary<string, bool>(); var query = new StringBuilder();
private bool _requireAll; private StringBuildervar _viewFieldsopenOperators = new StringBuilder()0;
#endregion if (TotalClauses > 0)
#region Public Query Properties (for retrieveing the query when ready) {
public string Query {query.Append("<Where>");
get { return BuildQuery(); }
}//When we have just one clause we can't use AND or OR.
/// <summary> if /// (_camlClauses.Count > 1)
Used when dealing with Client Object Model {
/// </summary> public string ViewXml var totalCamlPairs {= _camlClauses.Count - 1;
get //Math.DivRem(_CamlClauses.Count, 2, {out remainder) + remainder;
return string.Format("<View><Query>{0}</Query><ViewFields>{1}</ViewFields>{2}</View>", while (totalCamlPairs > 0)
TotalClauses == 0 ? string.Empty : Query, ViewFields,{
RowLimit.HasValue ? "<RowLimit>" + RowLimit.Value + "</RowLimit>query.Append(_requireAll ? "<And>" : string.Empty"<Or>");
} } totalCamlPairs--;
public string ViewFields { openOperators++;
get { return _viewFields.ToString(); } } }
public int TotalClauses {
}
get { return _camlClauses.Count; } var clausesAdded = 0;
} public int? RowLimit {foreach get; set; }
(var clause in _camlClauses)
#endregion #region{
public methods /// <summary> /// </summary>query.Append(clause);
/// <param name="requireAll">Uses an AND operation between CAML pairs. Uses OrclausesAdded++;
when false. All Words/Any Word</param> public void Begin(bool requireAll) if (clausesAdded > 1)
{ _camlClauses = new List<string>(); {
_requireAll = requireAll; _viewFields = new StringBuilder(query.Append(_requireAll ? "</And>" : "</Or>");
_orderByFields = new Dictionary<string, bool>(); openOperators--;
} public void AddClause(CamlOperator operation, string fieldRef, int value) }
{ }
AddClause(operation, fieldRef, value.ToString()); query.Append("</Where>");
}
public voidif AddClause(CamlOperator operation, string fieldRef)(_orderByFields.Count > 0)
{
_camlClausesquery.Add(string.Format("<{0}><FieldRef Name='{1}' /></{0}>",Append("<OrderBy>");
foreach (var new[] {operation.ToString(), fieldRef}));item in _orderByFields)
} {
public void AddClause(CamlOperator operation, string fieldRef, string value) { query.AppendFormat("<FieldRef Name='{0}' Ascending='{1}' />", item.Key, item.Value);
if (!string.IsNullOrEmpty(value)) {}
_camlClauses.Add(string.Formatquery.Append("<{0}><FieldRef Name='{1}' /><Value Type='Text'>{2}</Value></{0}>",/OrderBy>");
}
new[] {operationreturn query.ToString(),;
fieldRef, value})); }
} #endregion
} #region Private Variables
public void AddClause(CamlOperator operation, string fieldRef, string value, string valueType)private ICollection<string> _camlClauses = new List<string>();
private Dictionary<string, bool> _orderByFields {= new Dictionary<string, bool>();
private if (!string.IsNullOrEmpty(value))bool _requireAll;
private StringBuilder _viewFields = {new StringBuilder();
#endregion
_camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /><Value Type='{2}'>{3}</Value></{0}>", #region Public Query Properties (for retrieveing the query when ready)
public string Query
{
get { return BuildQuery(); }
}
/// <summary>
/// Used when dealing with Client Object Model
/// </summary>
public string ViewXml
{
get
{
string viewFields = string.Empty;
if (_viewFields != null && _viewFields.Length > 0)
new[] {operation.ToString(), fieldRef, valueType, value})); {
} } viewFields = $"<ViewFields>{_viewFields}</ViewFields>";
public void AddClauseWithLookupId(CamlOperator operation, string fieldRef, string value, string valueType) }
{ ifreturn (!string.IsNullOrEmpty(value))Format("<View{3}><Query>{0}</Query>{1}{2}</View>",
{ TotalClauses == 0 ? string.Empty : Query, viewFields,
_camlClauses.Add( RowLimit.HasValue string.Format("<{0}><FieldRef Name='{1}' LookupId='True' /><Value Type='{2}'>{3}</Value></{0}>",
? "<RowLimit>" + RowLimit.Value + "</RowLimit>" : string.Empty,
string.IsNullOrEmpty(ViewScope) new[] {operation.ToString(), fieldRef, valueType, value})? string.Empty : " " + ViewScope);
}
}
public voidstring AddViewField(string fieldRef)
ViewScope { get; set; }
{ public string ViewFields
_viewFields.AppendFormat("<FieldRef Name='{0}'/>", fieldRef);{
get { return _viewFields.ToString(); }
}
public void AddViewFields(string[] fieldRefs) public int TotalClauses
{ {
foreach (string fieldRef in fieldRefs) get { return _camlClauses.Count; }
{ }
public int? RowLimit { _viewFields.AppendFormat("<FieldRef Name='{0}'/>", fieldRef.Replace(" ", "_x0020_"));get; set; }
#endregion
#region public methods
} /// <summary>
} public void AddOrderBy(string fieldName, bool ascending)/// </summary>
/// <param name="requireAll">Uses an AND {operation between CAML pairs. Uses Or when false. All Words/Any Word</param>
_orderByFields.Add(fieldName, ascending); public void Begin(bool }requireAll)
#endregion{
#region Query Building _camlClauses = new List<string>();
private string BuildQuery() _requireAll {= requireAll;
var query_viewFields = new StringBuilder();
int openOperators_orderByFields = 0;new Dictionary<string, bool>();
}
if (TotalClauses > 0)
public void AddClause(CamlOperator {operation, string fieldRef, int value)
query.Append("<Where>");{
AddClause(operation, //When we have just one clause we can't use AND or OR.fieldRef, value.ToString());
}
public void AddClause(CamlOperator operation, string fieldRef)
if (_camlClauses.Count > 1) {
_camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' {/></{0}>",
new[] {operation.ToString(), fieldRef}));
int totalCamlPairs = _camlClauses.Count - 1; }
public void AddClause(CamlOperator operation, string fieldRef, string value)
//Math.DivRem(_CamlClauses.Count, 2, out remainder) + remainder;{
if (!string.IsNullOrEmpty(value))
while (totalCamlPairs > 0) {
_camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /><Value Type='Text'>{2}</Value></{0}>",
query.Append(_requireAll ? "<And>" : "<Or>"new[] {operation.ToString(), fieldRef, value}));
}
}
totalCamlPairs--; public void AddClause(CamlOperator operation, string openOperators++;
fieldRef, string value, string valueType)
{
} if (!string.IsNullOrEmpty(value))
} {
int clausesAdded = 0; _camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /><Value Type='{2}'>{3}</Value></{0}>",
foreach (string clause in _camlClauses)
operation, fieldRef, valueType, value));
}
{ }
public void query.Append(clause);
AddClauseWithLookupId(CamlOperator operation, string fieldRef, string value, string valueType)
{
clausesAdded++; if (!string.IsNullOrEmpty(value))
if (clausesAdded > 1) {
{_camlClauses.Add(
query.Append(_requireAll ? "</And>" : "</Or>");string.Format("<{0}><FieldRef Name='{1}' LookupId='True' /><Value Type='{2}'>{3}</Value></{0}>",
openOperators--;
operation, fieldRef, valueType, value));
}
}
public void query.Append("</Where>");
AddViewField(string fieldRef)
} {
if (_orderByFields.Count > 0)viewFields.AppendFormat("<FieldRef Name='{0}'/>", fieldRef);
}
{ public void AddViewFields(string[] fieldRefs)
query.Append("<OrderBy>");
{
foreach (var itemfieldRef in _orderByFields)
fieldRefs)
{
query_viewFields.AppendFormat("<FieldRef Name='{0}' Ascending='{1}' />", item.Key, item.ValuefieldRef.Replace(" ", "_x0020_"));
}
} }
public void query.Append("</OrderBy>");
AddOrderBy(string fieldName, bool ascending)
}{
return query.ToString(_orderByFields.Add(fieldName, ascending);
}
#endregion
}
|