{"id":190,"date":"2010-07-11T14:21:55","date_gmt":"2010-07-11T12:21:55","guid":{"rendered":"http:\/\/jsiegmund.wordpress.com\/2010\/07\/11\/constructing-dynamic-caml-queries-the-easy-way\/"},"modified":"2013-04-18T18:42:10","modified_gmt":"2013-04-18T17:42:10","slug":"constructing-dynamic-caml-queries-the-easy-way","status":"publish","type":"post","link":"http:\/\/blog.repsaj.nl\/index.php\/2010\/07\/constructing-dynamic-caml-queries-the-easy-way\/","title":{"rendered":"Constructing dynamic CAML queries: the easy way"},"content":{"rendered":"<p>For a project I&#8217;m working on, I needed a way to roll-up data across multiple sites. There aren&#8217;t much ways of doing that, but one good way is using the SPSiteDataQuery object. This object, which can be used with the object model (<span style=\"text-decoration: underline;\">not<\/span> the client ones unfortunately), can be used to fire queries to SharePoint which get data from multiple lists and multiple sites at once. You can specify which list types, content types and what fields to retrieve and, which this blog post is about, you can create a WHERE query to filter down the data.<\/p>\n<p>When you write queries for the SPSiteDataQuery object, you have to use CAML (Collaborative Application Markup Language). This comes down to writing properly formed XML in which you, for instance, specify which query you want to execute. Now sometimes you can just write a static query and use that, but other times you&#8217;ll need something a bit more dynamic. I was struggling with this, because I didn&#8217;t find a proper way of doing this. Until I ran into the <a href=\"http:\/\/www.u2u.be\/res\/tools\/camlquerybuilder.aspx\">U2U CAML Query Builder<\/a>, which seemed to do exactly what I needed.<\/p>\n<p>The great thing about this tool is that you, as a developer, can reuse the DLL&#8217;s in your own project. And with that option, writing CAML suddenly becomes a lot easier.<\/p>\n<p>I&#8217;ll only cover the Where query here, but you can use it for other CAML things too. Here are the most important thing to know:<\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: #2b91af;\">Builder<\/span> camlBuilder = <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">Builder<\/span>(U2U.SharePoint.CAML.Enumerations.<span style=\"color: #2b91af;\">CamlTypes<\/span>.Query);<br \/>\n<\/span><\/p>\n<p>Use <span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.AddWhereField<\/span> to add a field filter to the Where clause. Usage:<br \/>\n<span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.AddWhereField(<span style=\"color: #a31515;\">&#8220;FieldName&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Value&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Text&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Eq&#8221;<\/span>, <span style=\"color: blue;\">out<\/span> addCombinerNode);<br \/>\n<\/span><\/p>\n<p>Now you probably wonder what the addCombinerNode parameter is for; I honestly don&#8217;t know either. But since you don&#8217;t really need it for this purpose, who cares?<\/p>\n<p>Okay; this generates CAML, like this:<\/p>\n<p><span style=\"color: blue; font-family: Consolas; font-size: 10pt;\">&lt;<span style=\"color: #a31515;\">Query<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0&lt;<span style=\"color: #a31515;\">Where<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0&lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>&#8220;<span style=\"color: blue;\">FieldName<\/span>&#8220;<span style=\"color: blue;\">\u00a0\/&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>&#8220;<span style=\"color: blue;\">Text<\/span>&#8220;<span style=\"color: blue;\">&gt;<\/span>FieldValue<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0&lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">\u00a0\u00a0&lt;\/<span style=\"color: #a31515;\">Where<span style=\"color: blue;\">&gt;<\/span><br \/>\n<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Query<span style=\"color: blue;\">&gt;<\/span><br \/>\n<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/p>\n<p>Cool, saves some work. Now to get this dynamic, you need to know a few things about CAML. Combining multiple fields is done with And and Or nodes. Each And \/ Or node must have <span style=\"text-decoration: underline;\">exactly<\/span> two Boolean parts. The above CAML fragment (starting at Eq) represents one single Boolean value. So when you have two Eq&#8217;s, you can wrap those inside an And \/ Or node. If you have three though, you&#8217;ll need two And \/ Or nodes; one with two Eq&#8217;s in it, and one with one Eq and the other And \/ Or nore (since that represents a Boolean value too). Let me illustrate this with an example:<\/p>\n<pre><code><span style=\"color: blue; font-family: Consolas;\">&lt;<span style=\"color: #a31515;\">Query<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\r\n  <\/span><\/span><\/span><\/code><code><span style=\"color: blue; font-family: Consolas;\"><span style=\"color: #a31515;\"><span style=\"color: blue;\">&lt;<span style=\"color: #a31515;\">Where<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\r\n    &lt;<span style=\"color: #a31515;\">And<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">FieldName1<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>FieldValue<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     &lt;<span style=\"color: #a31515;\">And<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n         &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">FieldName2<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n         &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>FieldValue<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n         &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">FieldName3<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n         &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>FieldValue<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n       &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n     &lt;\/<span style=\"color: #a31515;\">And<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\r\n    &lt;\/<span style=\"color: #a31515;\">And<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\r\n  &lt;\/<span style=\"color: #a31515;\">Where<span style=\"color: blue;\">&gt;\r\n<\/span><span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Query<span style=\"color: blue;\">&gt;<\/span>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/code><\/pre>\n<p>So the main problem with constructing this CAML is that you need to &#8216;look ahead&#8217;; you can add the first node, but when a second comes in, you need to wrap that and the previous one with an And\/Or.<\/p>\n<p>To cope with this, I wrote two methods which can help. The first one is this one:<\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">private<\/span><br \/>\n<span style=\"color: #2b91af;\">XmlNode<\/span> ConstructAndOrTree(<span style=\"color: #2b91af;\">TreeType<\/span> andOr, <span style=\"color: blue;\">string<\/span> fieldName, <span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: blue;\">string<\/span>&gt; values, <span style=\"color: blue;\">string<\/span> fieldType, <span style=\"color: blue;\">string<\/span> operatorTag, <span style=\"color: #2b91af;\">XmlNode<\/span> parentNode, <span style=\"color: #2b91af;\">Builder<\/span> camlBuilder)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">bool<\/span> addCombinerNode;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: green;\">\/\/ when there are no values; return the rootNode<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">if<\/span> (values.Count == 0)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span><br \/>\n<span style=\"color: blue;\">null<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: green;\">\/\/ when there&#8217;s just one value; append the node and return <\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<span style=\"color: blue;\">if<\/span> (values.Count == 1)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> camlBuilder.AddWhereField(fieldName, values.Pop(), fieldType, operatorTag, <span style=\"color: blue;\">out<\/span> addCombinerNode);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: green;\">\/\/ when there&#8217;s multiple values; construct and and\/or node; append one value and recursively call this method<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">string<\/span> andOrTag = andOr == <span style=\"color: #2b91af;\">TreeType<\/span>.And ? <span style=\"color: #a31515;\">&#8220;And&#8221;<\/span> : <span style=\"color: #a31515;\">&#8220;Or&#8221;<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: #2b91af;\">XmlNode<\/span> andOrNode = camlBuilder.AddAndOrNode(andOrTag, <span style=\"color: blue;\">null<\/span>);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.AddWhereField(<span style=\"color: #a31515;\">&#8220;FieldName&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Value&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Text&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Eq&#8221;<\/span>, <span style=\"color: blue;\">out<\/span> addCombinerNode);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">andOrNode.AppendChild(camlBuilder.AddWhereField(fieldName, values.Pop(), fieldType, operatorTag, <span style=\"color: blue;\">out<\/span> addCombinerNode));<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">andOrNode.AppendChild(ConstructAndOrTree(andOr, fieldName, values, fieldType, operatorTag, andOrNode, camlBuilder));<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> andOrNode;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p>This one is used for multi-value parameters. For instance, suppose you want to query items where the Title equals &#8220;Value1&#8221; or &#8220;Value2&#8243; or Value3&#8221;. Use this method, pass in a stack with those three values and it will return the following XML tree:<\/p>\n<pre><code><span style=\"color: blue; font-family: Consolas;\">\u00a0\u00a0\u00a0\u00a0&lt;<span style=\"color: #a31515;\">Or<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Title<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>Value1<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      &lt;<span style=\"color: #a31515;\">Or<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n          &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Title<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n          &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>Value2<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n          &lt;<span style=\"color: #a31515;\">FieldRef<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Name<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Title<\/span>\"<span style=\"color: blue;\">\u00a0\/&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n          &lt;<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">\u00a0<span style=\"color: red;\">Type<span style=\"color: blue;\">=<\/span>\"<span style=\"color: blue;\">Text<\/span>\"<span style=\"color: blue;\">&gt;<\/span>Value3<span style=\"color: blue;\">&lt;\/<span style=\"color: #a31515;\">Value<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n        &lt;\/<span style=\"color: #a31515;\">Eq<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n      &lt;\/<span style=\"color: #a31515;\">Or<span style=\"color: blue;\">&gt;<\/span><span style=\"color: blue;\">\u00a0\u00a0\u00a0\u00a0\r\n    &lt;\/<span style=\"color: #a31515;\">Or<span style=\"color: blue;\">&gt;<\/span><\/span>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/code><\/pre>\n<p>So you now can build these trees dynamically for your multi-valued parameters. But, you still need to combine all the trees into one big three. That&#8217;s where this method comes in:<\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">private<\/span><br \/>\n<span style=\"color: #2b91af;\">XmlNode<\/span> CombineNodes(<span style=\"color: #2b91af;\">TreeType<\/span> andOr, <span style=\"color: #2b91af;\">XmlNode<\/span> node1, <span style=\"color: #2b91af;\">XmlNode<\/span> node2, <span style=\"color: #2b91af;\">Builder<\/span> camlBuilder)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: green;\">\/\/ create and and\/or node<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">string<\/span> andOrTag = andOr == <span style=\"color: #2b91af;\">TreeType<\/span>.And ? <span style=\"color: #a31515;\">&#8220;And&#8221;<\/span> : <span style=\"color: #a31515;\">&#8220;Or&#8221;<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: #2b91af;\">XmlNode<\/span> andOrNode = camlBuilder.AddAndOrNode(andOrTag, <span style=\"color: blue;\">null<\/span>);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: green;\">\/\/ when a node is null; there&#8217;s nothing to combine<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">if<\/span> (node1 == <span style=\"color: blue;\">null<\/span>)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> node2;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<span style=\"color: blue;\">if<\/span> (node2 == <span style=\"color: blue;\">null<\/span>)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> node1;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">andOrNode.AppendChild(node1);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">andOrNode.AppendChild(node2);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> andOrNode;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">private<\/span><br \/>\n<span style=\"color: #2b91af;\">XmlNode<\/span> CombineNodes(<span style=\"color: #2b91af;\">TreeType<\/span> andOr, <span style=\"color: #2b91af;\">Builder<\/span> camlBuilder, <span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: #2b91af;\">XmlNode<\/span>&gt; nodes)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">if<\/span> (nodes.Count == 0)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span><br \/>\n<span style=\"color: blue;\">null<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<span style=\"color: blue;\">if<\/span> (nodes.Count == 1)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> nodes.Pop();<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">else<\/span><br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">{<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><br \/>\n<span style=\"color: blue;\">return<\/span> CombineNodes(andOr, nodes.Pop(), CombineNodes(andOr, camlBuilder, nodes), camlBuilder);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">}<br \/>\n<\/span><\/p>\n<p>Use it like this:<\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">CombineNodes(<span style=\"color: #2b91af;\">TreeType<\/span>.And, camlBuilder, nodes);<br \/>\n<\/span><\/p>\n<p>The first parameter is an enum which represents either And or Or. The second is the U2U CAML query builder object, the third is again a stack, but this time with all XmlNodes representing the different XML trees. Now this comines everything with either And or Or nodes. Perhaps you need a bit more influence on that; in that case just skip the stack approach and call the upper CombineNodes method yourself.<\/p>\n<p>So with this, you can create (like I&#8217;ve done) a webservice which serves all items from a site collection rolled up; filtered by the parameters you want. Building the CAML becomes a lot easier, my code for instance is the following:<\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: #2b91af;\">Builder<\/span> camlBuilder = <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">Builder<\/span>(U2U.SharePoint.CAML.Enumerations.<span style=\"color: #2b91af;\">CamlTypes<\/span>.Query);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: blue;\">bool<\/span> addCombinerNode;<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ stack for multiple XML trees<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: #2b91af;\">XmlNode<\/span>&gt; nodes = <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: #2b91af;\">XmlNode<\/span>&gt;();<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ add parameters trees when parameters have been set<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: blue;\">if<\/span> (taskStates != <span style=\"color: blue;\">null<\/span> &amp;&amp; taskStates.Length &gt; 0)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">nodes.Push(ConstructAndOrTree(<span style=\"color: #2b91af;\">TreeType<\/span>.Or, <span style=\"color: #a31515;\">&#8220;TaskState&#8221;<\/span>, <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: blue;\">string<\/span>&gt;(taskStates), <span style=\"color: #a31515;\">&#8220;Choice&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Eq&#8221;<\/span>, camlBuilder.WhereNode.FirstChild, camlBuilder));<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: blue;\">if<\/span> (taskTypes != <span style=\"color: blue;\">null<\/span> &amp;&amp; taskTypes.Length &gt; 0)<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">nodes.Push(ConstructAndOrTree(<span style=\"color: #2b91af;\">TreeType<\/span>.Or, <span style=\"color: #a31515;\">&#8220;TaskType&#8221;<\/span>, <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">Stack<\/span>&lt;<span style=\"color: blue;\">string<\/span>&gt;(taskTypes), <span style=\"color: #a31515;\">&#8220;Choice&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Eq&#8221;<\/span>, camlBuilder.WhereNode.FirstChild, camlBuilder));<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ always add content type query parameter<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">nodes.Push(camlBuilder.AddWhereField(<span style=\"color: #a31515;\">&#8220;ContentType&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Task&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Computed&#8221;<\/span>, <span style=\"color: #a31515;\">&#8220;Eq&#8221;<\/span>, <span style=\"color: blue;\">out<\/span> addCombinerNode));<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ recursively combine trees \/ nodes with And nodes<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: #2b91af;\">XmlNode<\/span> tree = CombineNodes(<span style=\"color: #2b91af;\">TreeType<\/span>.And, camlBuilder, nodes);<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ set the resulting XML tree as child of the Where node<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.WhereNode.RemoveAll();<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.WhereNode.AppendChild(tree);<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ add the view fields<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.AddViewField(<span style=\"color: #a31515;\">&#8220;Title&#8221;<\/span>);<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">camlBuilder.AddViewField(<span style=\"color: #a31515;\">&#8220;ID&#8221;<\/span>);<br \/>\n<\/span><\/p>\n<p><span style=\"color: green; font-family: Consolas; font-size: 9pt;\">\/\/ build SPSiteDataQuery object and set members<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\"><span style=\"color: #2b91af;\">SPSiteDataQuery<\/span> apQuery = <span style=\"color: blue;\">new<\/span><br \/>\n<span style=\"color: #2b91af;\">SPSiteDataQuery<\/span>();<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">apQuery.Lists = <span style=\"color: #a31515;\">&#8220;&lt;Lists ServerTemplate=&#8217;100&#8242; \/&gt;&#8221;<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">apQuery.Webs = <span style=\"color: #a31515;\">&#8220;&lt;Webs Scope=&#8217;SiteCollection&#8217; \/&gt;&#8221;<\/span>;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">apQuery.ViewFields = camlBuilder.ViewFieldsNode.InnerXml;<br \/>\n<\/span><\/p>\n<p><span style=\"font-family: Consolas; font-size: 9pt;\">apQuery.Query = camlBuilder.WhereNode.OuterXml;<br \/>\n<\/span><\/p>\n<p>There you have it; building complicated CAML queries in a simple way; special thanks to the guys at U2U for providing their CAML builder for free!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>For a project I&#8217;m working on, I needed a way to roll-up data across multiple sites. There aren&#8217;t much ways of doing that, but one good way is using the SPSiteDataQuery object. This object, which can be used with the object model (not the client ones unfortunately), can be used to fire queries to SharePoint<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[34],"tags":[7,13,30],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3KFR1-34","_links":{"self":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts\/190"}],"collection":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/comments?post=190"}],"version-history":[{"count":0,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/posts\/190\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/media?parent=190"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/categories?post=190"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.repsaj.nl\/index.php\/wp-json\/wp\/v2\/tags?post=190"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}