CamlBuilder - Caml Query Wrapper

Script

Name

Description

Last Modified Date

Download

CamlBuilder.cs

Wrapper over CAML queries.

20/11/2014

None

CamlBuilder.cs
 /// <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 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 Query Building
        private string BuildQuery()
        {
            var query = new StringBuilder();
            var openOperators = 0;
            if (TotalClauses > 0)
            {
                query.Append("<Where>");
                //When we have just one clause we can't use AND or OR.
                if (_camlClauses.Count > 1)
                {
                    var totalCamlPairs = _camlClauses.Count - 1;
                    //Math.DivRem(_CamlClauses.Count, 2, out remainder) + remainder;
                    while (totalCamlPairs > 0)
                    {
                        query.Append(_requireAll ? "<And>" : "<Or>");
                        totalCamlPairs--;
                        openOperators++;
                    }
                }
                var clausesAdded = 0;
                foreach (var clause in _camlClauses)
                {
                    query.Append(clause);
                    clausesAdded++;
                    if (clausesAdded > 1)
                    {
                        query.Append(_requireAll ? "</And>" : "</Or>");
                        openOperators--;
                    }
                }
                query.Append("</Where>");
            }
            if (_orderByFields.Count > 0)
            {
                query.Append("<OrderBy>");
                foreach (var item in _orderByFields)
                {
                    query.AppendFormat("<FieldRef Name='{0}' Ascending='{1}' />", item.Key, item.Value);
                }
                query.Append("</OrderBy>");
            }
            return query.ToString();
        }
        #endregion
        #region Private Variables
        private ICollection<string> _camlClauses = new List<string>();
        private Dictionary<string, bool> _orderByFields = new Dictionary<string, bool>();
        private bool _requireAll;
        private StringBuilder _viewFields = new StringBuilder();
        #endregion
        #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)
                {
                    viewFields = $"<ViewFields>{_viewFields}</ViewFields>";
                }
                return string.Format("<View{3}><Query>{0}</Query>{1}{2}</View>",
                    TotalClauses == 0 ? string.Empty : Query, viewFields,
                    RowLimit.HasValue ? "<RowLimit>" + RowLimit.Value + "</RowLimit>" : string.Empty,
                    string.IsNullOrEmpty(ViewScope) ? string.Empty : " " + ViewScope);
            }
        }
        public string ViewScope { get; set; }
        public string ViewFields
        {
            get { return _viewFields.ToString(); }
        }
        public int TotalClauses
        {
            get { return _camlClauses.Count; }
        }
        public int? RowLimit { get; set; }
        #endregion
        #region public methods
        /// <summary>
        /// </summary>
        /// <param name="requireAll">Uses an AND operation between CAML pairs.  Uses Or when false. All Words/Any Word</param>
        public void Begin(bool requireAll)
        {
            _camlClauses = new List<string>();
            _requireAll = requireAll;
            _viewFields = new StringBuilder();
            _orderByFields = new Dictionary<string, bool>();
        }
     
        public void AddClause(CamlOperator operation, string fieldRef, int value)
        {
            AddClause(operation, fieldRef, value.ToString());
        }
        public void AddClause(CamlOperator operation, string fieldRef)
        {
            _camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /></{0}>",
                new[] {operation.ToString(), fieldRef}));
        }
        public void AddClause(CamlOperator operation, string fieldRef, string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                _camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /><Value Type='Text'>{2}</Value></{0}>",
                    new[] {operation.ToString(), fieldRef, value}));
            }
        }
        public void AddClause(CamlOperator operation, string fieldRef, string value, string valueType)
        {
            if (!string.IsNullOrEmpty(value))
            {
                _camlClauses.Add(string.Format("<{0}><FieldRef Name='{1}' /><Value Type='{2}'>{3}</Value></{0}>",
                    operation, fieldRef, valueType, value));
            }
        }
        public void AddClauseWithLookupId(CamlOperator operation, string fieldRef, string value, string valueType)
        {
            if (!string.IsNullOrEmpty(value))
            {
                _camlClauses.Add(
                    string.Format("<{0}><FieldRef Name='{1}' LookupId='True' /><Value Type='{2}'>{3}</Value></{0}>",
                        operation, fieldRef, valueType, value));
            }
        }
        public void AddViewField(string fieldRef)
        {
            _viewFields.AppendFormat("<FieldRef Name='{0}'/>", fieldRef);
        }
        public void AddViewFields(string[] fieldRefs)
        {
            foreach (var fieldRef in fieldRefs)
            {
                _viewFields.AppendFormat("<FieldRef Name='{0}'/>", fieldRef.Replace(" ", "_x0020_"));
            }
        }
        public void AddOrderBy(string fieldName, bool ascending)
        {
            _orderByFields.Add(fieldName, ascending);
        }
        #endregion
    }

CodeMonkey Software is a division of JCHMedia www.jchmedia.com