4
// Lluis Sanchez Gual <lluis@novell.com>
6
// Copyright (c) 2008 Novell, Inc (http://www.novell.com)
8
// Permission is hereby granted, free of charge, to any person obtaining a copy
9
// of this software and associated documentation files (the "Software"), to deal
10
// in the Software without restriction, including without limitation the rights
11
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
// copies of the Software, and to permit persons to whom the Software is
13
// furnished to do so, subject to the following conditions:
15
// The above copyright notice and this permission notice shall be included in
16
// all copies or substantial portions of the Software.
18
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
using System.Collections.Generic;
33
namespace MonoDevelop.Projects.Formats.MSBuild
37
public XmlDocument doc;
38
Dictionary<XmlElement,MSBuildObject> elemCache = new Dictionary<XmlElement,MSBuildObject> ();
40
public const string Schema = "http://schemas.microsoft.com/developer/msbuild/2003";
41
static XmlNamespaceManager manager;
45
internal static XmlNamespaceManager XmlNamespaceManager {
47
if (manager == null) {
48
manager = new XmlNamespaceManager (new NameTable ());
49
manager.AddNamespace ("tns", Schema);
55
public MSBuildProject ()
57
doc = new XmlDocument ();
58
doc.PreserveWhitespace = false;
59
doc.AppendChild (doc.CreateElement (null, "Project", Schema));
62
public void Load (string file)
64
doc = new XmlDocument ();
65
doc.PreserveWhitespace = false;
69
public void LoadXml (string xml)
71
doc = new XmlDocument ();
72
doc.PreserveWhitespace = false;
74
useCrLf = CountNewLines ("\r\n", xml) > (CountNewLines ("\n", xml) / 2);
77
public void Save (string file)
79
StreamWriter sw = new StreamWriter (file);
89
int CountNewLines (string nl, string text)
96
i = text.IndexOf (nl, i);
102
public string DefaultTargets {
103
get { return doc.DocumentElement.GetAttribute ("DefaultTargets"); }
104
set { doc.DocumentElement.SetAttribute ("DefaultTargets", value); }
107
public string ToolsVersion {
108
get { return doc.DocumentElement.GetAttribute ("ToolsVersion"); }
110
if (!string.IsNullOrEmpty (value))
111
doc.DocumentElement.SetAttribute ("ToolsVersion", value);
113
doc.DocumentElement.RemoveAttribute ("ToolsVersion");
117
public void AddNewImport (string name, string condition)
119
XmlElement elem = doc.CreateElement (null, "Import", MSBuildProject.Schema);
120
doc.DocumentElement.AppendChild (elem);
121
elem.SetAttribute ("Project", name);
124
public MSBuildPropertyGroup GetGlobalPropertyGroup ()
126
foreach (MSBuildPropertyGroup grp in PropertyGroups) {
127
if (grp.Condition.Length == 0)
133
public MSBuildPropertyGroup AddNewPropertyGroup (bool insertAtEnd)
135
XmlElement elem = doc.CreateElement (null, "PropertyGroup", MSBuildProject.Schema);
137
XmlElement last = doc.DocumentElement.SelectSingleNode ("tns:PropertyGroup[last()]", XmlNamespaceManager) as XmlElement;
139
doc.DocumentElement.InsertAfter (elem, last);
141
doc.DocumentElement.AppendChild (elem);
143
return GetGroup (elem);
146
public IEnumerable<MSBuildItem> GetAllItems ()
148
foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:ItemGroup/*", XmlNamespaceManager)) {
149
yield return GetItem (elem);
153
public IEnumerable<MSBuildItem> GetAllItems (params string[] names)
155
string name = string.Join ("|tns:ItemGroup/tns:", names);
156
foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:ItemGroup/tns:" + name, XmlNamespaceManager)) {
157
yield return GetItem (elem);
161
public IEnumerable<MSBuildPropertyGroup> PropertyGroups {
163
foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:PropertyGroup", XmlNamespaceManager))
164
yield return GetGroup (elem);
168
public IEnumerable<MSBuildItemGroup> ItemGroups {
170
foreach (XmlElement elem in doc.DocumentElement.SelectNodes ("tns:ItemGroup", XmlNamespaceManager))
171
yield return GetItemGroup (elem);
175
public MSBuildItemGroup AddNewItemGroup ()
177
XmlElement elem = doc.CreateElement (null, "ItemGroup", MSBuildProject.Schema);
178
doc.DocumentElement.AppendChild (elem);
179
return GetItemGroup (elem);
182
public MSBuildItem AddNewItem (string name, string include)
184
XmlElement elem = (XmlElement) doc.DocumentElement.SelectSingleNode ("tns:ItemGroup/" + name, XmlNamespaceManager);
186
MSBuildItemGroup grp = GetItemGroup ((XmlElement) elem.ParentNode);
187
return grp.AddNewItem (name, include);
189
MSBuildItemGroup grp = AddNewItemGroup ();
190
return grp.AddNewItem (name, include);
194
public string GetProjectExtensions (string section)
196
XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement;
198
return elem.InnerXml;
203
public void SetProjectExtensions (string section, string value)
205
XmlElement elem = doc.DocumentElement ["ProjectExtensions", MSBuildProject.Schema];
207
elem = doc.CreateElement (null, "ProjectExtensions", MSBuildProject.Schema);
208
doc.DocumentElement.AppendChild (elem);
210
XmlElement sec = elem [section];
212
sec = doc.CreateElement (null, section, MSBuildProject.Schema);
213
elem.AppendChild (sec);
215
sec.InnerXml = value;
218
public void RemoveProjectExtensions (string section)
220
XmlElement elem = doc.DocumentElement.SelectSingleNode ("tns:ProjectExtensions/tns:" + section, XmlNamespaceManager) as XmlElement;
222
XmlElement parent = (XmlElement) elem.ParentNode;
223
parent.RemoveChild (elem);
224
if (!parent.HasChildNodes)
225
parent.ParentNode.RemoveChild (parent);
229
public void RemoveItem (MSBuildItem item)
231
elemCache.Remove (item.Element);
232
XmlElement parent = (XmlElement) item.Element.ParentNode;
233
item.Element.ParentNode.RemoveChild (item.Element);
234
if (parent.ChildNodes.Count == 0) {
235
elemCache.Remove (parent);
236
parent.ParentNode.RemoveChild (parent);
240
internal MSBuildItem GetItem (XmlElement elem)
243
if (elemCache.TryGetValue (elem, out ob))
244
return (MSBuildItem) ob;
245
MSBuildItem it = new MSBuildItem (elem);
246
elemCache [elem] = it;
250
MSBuildPropertyGroup GetGroup (XmlElement elem)
253
if (elemCache.TryGetValue (elem, out ob))
254
return (MSBuildPropertyGroup) ob;
255
MSBuildPropertyGroup it = new MSBuildPropertyGroup (elem);
256
elemCache [elem] = it;
260
MSBuildItemGroup GetItemGroup (XmlElement elem)
263
if (elemCache.TryGetValue (elem, out ob))
264
return (MSBuildItemGroup) ob;
265
MSBuildItemGroup it = new MSBuildItemGroup (this, elem);
266
elemCache [elem] = it;
271
public class MSBuildObject
275
public MSBuildObject (XmlElement elem)
280
public XmlElement Element {
284
protected XmlElement AddChildElement (string name)
286
XmlElement e = elem.OwnerDocument.CreateElement (null, name, MSBuildProject.Schema);
287
elem.AppendChild (e);
291
public string Condition {
293
return Element.GetAttribute ("Condition");
296
if (string.IsNullOrEmpty (value))
297
Element.RemoveAttribute ("Condition");
299
Element.SetAttribute ("Condition", value);
304
class MSBuildProperty: MSBuildObject
306
public MSBuildProperty (XmlElement elem): base (elem)
311
get { return Element.Name; }
314
public string Value {
316
return Element.InnerXml;
319
Element.InnerXml = value;
324
class MSBuildPropertyGroup: MSBuildObject
326
Dictionary<string,MSBuildProperty> properties = new Dictionary<string,MSBuildProperty> ();
328
public MSBuildPropertyGroup (XmlElement elem): base (elem)
332
public MSBuildProperty GetProperty (string name)
334
MSBuildProperty prop;
335
if (properties.TryGetValue (name, out prop))
337
XmlElement propElem = Element [name, MSBuildProject.Schema];
338
if (propElem != null) {
339
prop = new MSBuildProperty (propElem);
340
properties [name] = prop;
347
public IEnumerable<MSBuildProperty> Properties {
349
foreach (XmlNode node in Element.ChildNodes) {
350
XmlElement pelem = node as XmlElement;
353
MSBuildProperty prop;
354
if (properties.TryGetValue (pelem.Name, out prop))
357
prop = new MSBuildProperty (pelem);
358
properties [pelem.Name] = prop;
365
public void SetPropertyValue (string name, string value)
367
MSBuildProperty prop = GetProperty (name);
369
XmlElement pelem = AddChildElement (name);
370
prop = new MSBuildProperty (pelem);
371
properties [name] = prop;
376
public string GetPropertyValue (string name)
378
MSBuildProperty prop = GetProperty (name);
385
public void RemoveProperty (string name)
387
MSBuildProperty prop = GetProperty (name);
389
properties.Remove (name);
390
Element.RemoveChild (prop.Element);
394
public void RemoveAllProperties ()
396
List<XmlNode> toDelete = new List<XmlNode> ();
397
foreach (XmlNode node in Element.ChildNodes) {
398
if (node is XmlElement)
401
foreach (XmlNode node in toDelete)
402
Element.RemoveChild (node);
406
public static MSBuildPropertyGroup Merge (MSBuildPropertyGroup g1, MSBuildPropertyGroup g2)
408
XmlElement elem = g1.Element.OwnerDocument.CreateElement (null, "PropertyGroup", MSBuildProject.Schema);
409
MSBuildPropertyGroup grp = new MSBuildPropertyGroup (elem);
410
foreach (MSBuildProperty prop in g1.Properties)
411
grp.SetPropertyValue (prop.Name, prop.Value);
412
foreach (MSBuildProperty prop in g2.Properties)
413
grp.SetPropertyValue (prop.Name, prop.Value);
417
public void UnMerge (MSBuildPropertyGroup baseGrp)
419
foreach (MSBuildProperty prop in baseGrp.Properties) {
420
MSBuildProperty thisProp = GetProperty (prop.Name);
421
if (thisProp != null && prop.Value == thisProp.Value)
422
RemoveProperty (prop.Name);
426
public override string ToString()
428
string s = "[MSBuildPropertyGroup:";
429
foreach (MSBuildProperty prop in Properties)
430
s += " " + prop.Name + "=" + prop.Value;
436
class MSBuildItem: MSBuildObject
438
public MSBuildItem (XmlElement elem): base (elem)
442
public string Include {
443
get { return Element.GetAttribute ("Include"); }
444
set { Element.SetAttribute ("Include", value); }
448
get { return Element.Name; }
451
public bool HasMetadata (string name)
453
return Element [name, MSBuildProject.Schema] != null;
456
public void SetMetadata (string name, string value)
458
SetMetadata (name, value, true);
461
public void SetMetadata (string name, string value, bool isLiteral)
463
XmlElement elem = Element [name, MSBuildProject.Schema];
465
elem = AddChildElement (name);
466
Element.AppendChild (elem);
468
elem.InnerXml = value;
471
public void UnsetMetadata (string name)
473
XmlElement elem = Element [name, MSBuildProject.Schema];
475
Element.RemoveChild (elem);
478
public string GetMetadata (string name)
480
XmlElement elem = Element [name, MSBuildProject.Schema];
482
return elem.InnerXml;
488
class MSBuildItemGroup: MSBuildObject
490
MSBuildProject parent;
492
internal MSBuildItemGroup (MSBuildProject parent, XmlElement elem): base (elem)
494
this.parent = parent;
497
public MSBuildItem AddNewItem (string name, string include)
499
XmlElement elem = AddChildElement (name);
500
MSBuildItem it = parent.GetItem (elem);
501
it.Include = include;
505
public IEnumerable<MSBuildItem> Items {
507
foreach (XmlNode node in Element.ChildNodes) {
508
XmlElement elem = node as XmlElement;
510
yield return parent.GetItem (elem);