Merge remote-tracking branch 'upstream/master'
[mono.git] / mcs / class / System.Xml.Linq / System.Xml.Linq / XElement.cs
1 //
2 // Authors:
3 //   Atsushi Enomoto
4 //
5 // Copyright 2007 Novell (http://www.novell.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
14 // 
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
17 // 
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 //
26
27 using System;
28 using System.Collections;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Linq;
32 using System.Text;
33 using System.Xml;
34 using System.Xml.Schema;
35 using System.Xml.Serialization;
36
37 namespace System.Xml.Linq
38 {
39         [XmlSchemaProvider (null, IsAny = true)]
40         public class XElement : XContainer, IXmlSerializable
41         {
42                 static IEnumerable <XElement> emptySequence =
43                         new List <XElement> ();
44
45                 public static IEnumerable <XElement> EmptySequence {
46                         get { return emptySequence; }
47                 }
48
49                 XName name;
50                 XAttribute attr_first, attr_last;
51                 bool explicit_is_empty = true;
52
53                 public XElement (XName name, object content)
54                 {
55                         this.name = name;
56                         Add (content);
57                 }
58
59                 public XElement (XElement other)
60                 {
61                         name = other.name;
62                         Add (other.Attributes ());
63                         Add (other.Nodes ());
64                 }
65
66                 public XElement (XName name)
67                 {
68                         this.name = name;
69                 }
70
71                 public XElement (XName name, params object [] content)
72                 {
73                         this.name = name;
74                         Add (content);
75                 }
76
77                 public XElement (XStreamingElement other)
78                 {
79                         this.name = other.Name;
80                         Add (other.Contents);
81                 }
82
83                 [CLSCompliant (false)]
84                 public static explicit operator bool (XElement element)
85                 {
86                         if (element == null)
87                                 throw new ArgumentNullException ("element");
88                         return XUtil.ConvertToBoolean (element.Value);
89                 }
90
91                 [CLSCompliant (false)]
92                 public static explicit operator bool? (XElement element)
93                 {
94                         if (element == null)
95                                 return null;
96                         
97                         return element.Value == null ? (bool?) null : XUtil.ConvertToBoolean (element.Value);
98                 }
99
100                 [CLSCompliant (false)]
101                 public static explicit operator DateTime (XElement element)
102                 {
103                         if (element == null)
104                                 throw new ArgumentNullException ("element");
105                         return XUtil.ToDateTime (element.Value);
106                 }
107
108                 [CLSCompliant (false)]
109                 public static explicit operator DateTime? (XElement element)
110                 {
111                         if (element == null)
112                                 return null;
113                         
114                         return element.Value == null ? (DateTime?) null : XUtil.ToDateTime (element.Value);
115                 }
116
117 #if !TARGET_JVM // Same as for System.Xml.XmlConvert.ToDateTimeOffset
118
119                 [CLSCompliant (false)]
120                 public static explicit operator DateTimeOffset (XElement element)
121                 {
122                         if (element == null)
123                                 throw new ArgumentNullException ("element");
124                         return XmlConvert.ToDateTimeOffset (element.Value);
125                 }
126
127                 [CLSCompliant (false)]
128                 public static explicit operator DateTimeOffset? (XElement element)
129                 {
130                         if (element == null)
131                                 return null;
132                         
133                         return element.Value == null ? (DateTimeOffset?) null : XmlConvert.ToDateTimeOffset (element.Value);
134                 }
135
136 #endif
137
138                 [CLSCompliant (false)]
139                 public static explicit operator decimal (XElement element)
140                 {
141                         if (element == null)
142                                 throw new ArgumentNullException ("element");
143                         return XmlConvert.ToDecimal (element.Value);
144                 }
145
146                 [CLSCompliant (false)]
147                 public static explicit operator decimal? (XElement element)
148                 {
149                         if (element == null)
150                                 return null;
151                         
152                         return element.Value == null ? (decimal?) null : XmlConvert.ToDecimal (element.Value);
153                 }
154
155                 [CLSCompliant (false)]
156                 public static explicit operator double (XElement element)
157                 {
158                         if (element == null)
159                                 throw new ArgumentNullException ("element");
160                         return XmlConvert.ToDouble (element.Value);
161                 }
162
163                 [CLSCompliant (false)]
164                 public static explicit operator double? (XElement element)
165                 {
166                         if (element == null)
167                                 return null;
168                         
169                         return element.Value == null ? (double?) null : XmlConvert.ToDouble (element.Value);
170                 }
171
172                 [CLSCompliant (false)]
173                 public static explicit operator float (XElement element)
174                 {
175                         if (element == null)
176                                 throw new ArgumentNullException ("element");
177                         return XmlConvert.ToSingle (element.Value);
178                 }
179
180                 [CLSCompliant (false)]
181                 public static explicit operator float? (XElement element)
182                 {
183                         if (element == null)
184                                 return null;
185                         
186                         return element.Value == null ? (float?) null : XmlConvert.ToSingle (element.Value);
187                 }
188
189                 [CLSCompliant (false)]
190                 public static explicit operator Guid (XElement element)
191                 {
192                         if (element == null)
193                                 throw new ArgumentNullException ("element");
194                         return XmlConvert.ToGuid (element.Value);
195                 }
196
197                 [CLSCompliant (false)]
198                 public static explicit operator Guid? (XElement element)
199                 {
200                         if (element == null)
201                                 return null;
202                         
203                         return element.Value == null ? (Guid?) null : XmlConvert.ToGuid (element.Value);
204                 }
205
206                 [CLSCompliant (false)]
207                 public static explicit operator int (XElement element)
208                 {
209                         if (element == null)
210                                 throw new ArgumentNullException ("element");
211                         return XmlConvert.ToInt32 (element.Value);
212                 }
213
214                 [CLSCompliant (false)]
215                 public static explicit operator int? (XElement element)
216                 {
217                         if (element == null)
218                                 return null;
219                         
220                         return element.Value == null ? (int?) null : XmlConvert.ToInt32 (element.Value);
221                 }
222
223                 [CLSCompliant (false)]
224                 public static explicit operator long (XElement element)
225                 {
226                         if (element == null)
227                                 throw new ArgumentNullException ("element");
228                         return XmlConvert.ToInt64 (element.Value);
229                 }
230
231                 [CLSCompliant (false)]
232                 public static explicit operator long? (XElement element)
233                 {
234                         if (element == null)
235                                 return null;
236                         
237                         return element.Value == null ? (long?) null : XmlConvert.ToInt64 (element.Value);
238                 }
239
240                 [CLSCompliant (false)]
241                 public static explicit operator uint (XElement element)
242                 {
243                         if (element == null)
244                                 throw new ArgumentNullException ("element");
245                         return XmlConvert.ToUInt32 (element.Value);
246                 }
247
248                 [CLSCompliant (false)]
249                 public static explicit operator uint? (XElement element)
250                 {
251                         if (element == null)
252                                 return null;
253                         
254                         return element.Value == null ? (uint?) null : XmlConvert.ToUInt32 (element.Value);
255                 }
256
257                 [CLSCompliant (false)]
258                 public static explicit operator ulong (XElement element)
259                 {
260                         if (element == null)
261                                 throw new ArgumentNullException ("element");
262                         return XmlConvert.ToUInt64 (element.Value);
263                 }
264
265                 [CLSCompliant (false)]
266                 public static explicit operator ulong? (XElement element)
267                 {
268                         if (element == null)
269                                 return null;
270                         
271                         return element.Value == null ? (ulong?) null : XmlConvert.ToUInt64 (element.Value);
272                 }
273
274                 [CLSCompliant (false)]
275                 public static explicit operator TimeSpan (XElement element)
276                 {
277                         if (element == null)
278                                 throw new ArgumentNullException ("element");
279                         return XmlConvert.ToTimeSpan (element.Value);
280                 }
281
282                 [CLSCompliant (false)]
283                 public static explicit operator TimeSpan? (XElement element)
284                 {
285                         if (element == null)
286                                 return null;
287                         
288                         return element.Value == null ? (TimeSpan?) null : XmlConvert.ToTimeSpan (element.Value);
289                 }
290
291                 [CLSCompliant (false)]
292                 public static explicit operator string (XElement element)
293                 {
294                         if (element == null)
295                                 return null;
296                         
297                         return element.Value;
298                 }
299
300                 public XAttribute FirstAttribute {
301                         get { return attr_first; }
302                         internal set { attr_first = value; }
303                 }
304
305                 public XAttribute LastAttribute {
306                         get { return attr_last; }
307                         internal set { attr_last = value; }
308                 }
309
310                 public bool HasAttributes {
311                         get { return attr_first != null; }
312                 }
313
314                 public bool HasElements {
315                         get {
316                                 foreach (object o in Nodes ())
317                                         if (o is XElement)
318                                                 return true;
319                                 return false;
320                         }
321                 }
322
323                 public bool IsEmpty {
324                         get { return !Nodes ().GetEnumerator ().MoveNext () && explicit_is_empty; }
325                         internal set { explicit_is_empty = value; }
326                 }
327
328                 public XName Name {
329                         get { return name; }
330                         set {
331                                 if (value == null)
332                                         throw new ArgumentNullException ("Name");
333                                 OnNameChanging (this);
334                                 name = value;
335                                 OnNameChanged (this);
336                         }
337                 }
338
339                 public override XmlNodeType NodeType {
340                         get { return XmlNodeType.Element; }
341                 }
342
343                 public string Value {
344                         get {
345                                 StringBuilder sb = null;
346                                 foreach (XNode n in Nodes ()) {
347                                         if (sb == null)
348                                                 sb = new StringBuilder ();
349                                         if (n is XText)
350                                                 sb.Append (((XText) n).Value);
351                                         else if (n is XElement)
352                                                 sb.Append (((XElement) n).Value);
353                                 }
354                                 return sb == null ? String.Empty : sb.ToString ();
355                         }
356                         set {
357                                 RemoveNodes ();
358                                 Add (value);
359                         }
360                 }
361
362                 IEnumerable <XElement> GetAncestorList (XName name, bool getMeIn)
363                 {
364                         List <XElement> list = new List <XElement> ();
365                         if (getMeIn)
366                                 list.Add (this);
367                         for (XElement el = Parent as XElement; el != null; el = el.Parent as XElement)
368                                 if (name == null || el.Name == name)
369                                         list.Add (el);
370                         return list;
371                 }
372
373                 public XAttribute Attribute (XName name)
374                 {
375                         foreach (XAttribute a in Attributes ())
376                                 if (a.Name == name)
377                                         return a;
378                         return null;
379                 }
380
381                 public IEnumerable <XAttribute> Attributes ()
382                 {
383                         XAttribute next;
384                         for (XAttribute a = attr_first; a != null; a = next) {
385                                 next = a.NextAttribute;
386                                 yield return a;
387                         }
388                 }
389
390                 // huh?
391                 public IEnumerable <XAttribute> Attributes (XName name)
392                 {
393                         foreach (XAttribute a in Attributes ())
394                                 if (a.Name == name)
395                                         yield return a;
396                 }
397
398                 static void DefineDefaultSettings (XmlReaderSettings settings, LoadOptions options)
399                 {
400 #if MOONLIGHT
401                         // 2.1 has a DtdProcessing property which defaults to DtdProcessing.Prohibit
402                         settings.DtdProcessing = DtdProcessing.Parse;
403 #else
404                         settings.ProhibitDtd = false;
405 #endif
406
407                         settings.IgnoreWhitespace = (options & LoadOptions.PreserveWhitespace) == 0;
408                 }
409
410                 static XmlReaderSettings CreateDefaultSettings (LoadOptions options)
411                 {
412                         var settings = new XmlReaderSettings ();
413                         DefineDefaultSettings (settings, options);
414                         return settings;
415                 }
416
417                 public static XElement Load (string uri)
418                 {
419                         return Load (uri, LoadOptions.None);
420                 }
421
422                 public static XElement Load (string uri, LoadOptions options)
423                 {
424                         XmlReaderSettings s = CreateDefaultSettings (options);
425
426                         using (XmlReader r = XmlReader.Create (uri, s)) {
427                                 return LoadCore (r, options);
428                         }
429                 }
430
431                 public static XElement Load (TextReader textReader)
432                 {
433                         return Load (textReader, LoadOptions.None);
434                 }
435
436                 public static XElement Load (TextReader textReader, LoadOptions options)
437                 {
438                         XmlReaderSettings s = CreateDefaultSettings (options);
439
440                         using (XmlReader r = XmlReader.Create (textReader, s)) {
441                                 return LoadCore (r, options);
442                         }
443                 }
444
445                 public static XElement Load (XmlReader reader)
446                 {
447                         return Load (reader, LoadOptions.None);
448                 }
449
450                 public static XElement Load (XmlReader reader, LoadOptions options)
451                 {
452                         XmlReaderSettings s = reader.Settings != null ? reader.Settings.Clone () : new XmlReaderSettings ();
453                         DefineDefaultSettings (s, options);
454
455                         using (XmlReader r = XmlReader.Create (reader, s)) {
456                                 return LoadCore (r, options);
457                         }
458                 }
459
460 #if MOONLIGHT || MOBILE || NET_4_0
461                 public static XElement Load (Stream stream)
462                 {
463                         return Load (stream, LoadOptions.None);
464                 }
465
466                 public static XElement Load (Stream stream, LoadOptions options)
467                 {
468                         XmlReaderSettings s = new XmlReaderSettings ();
469                         DefineDefaultSettings (s, options);
470
471                         using (XmlReader r = XmlReader.Create (stream, s)) {
472                                 return LoadCore (r, options);
473                         }
474                 }
475 #endif
476
477                 internal static XElement LoadCore (XmlReader r, LoadOptions options)
478                 {
479                         r.MoveToContent ();
480                         if (r.NodeType != XmlNodeType.Element)
481                                 throw new InvalidOperationException ("The XmlReader must be positioned at an element");
482                         XName name = XName.Get (r.LocalName, r.NamespaceURI);
483                         XElement e = new XElement (name);
484                         e.FillLineInfoAndBaseUri (r, options);
485
486                         if (r.MoveToFirstAttribute ()) {
487                                 do {
488                                         // not sure how current Orcas behavior makes sense here though ...
489                                         if (r.LocalName == "xmlns" && r.NamespaceURI == XNamespace.Xmlns.NamespaceName)
490                                                 e.SetAttributeValue (XNamespace.None.GetName ("xmlns"), r.Value);
491                                         else
492                                                 e.SetAttributeValue (XName.Get (r.LocalName, r.NamespaceURI), r.Value);
493                                         e.LastAttribute.FillLineInfoAndBaseUri (r, options);
494                                 } while (r.MoveToNextAttribute ());
495                                 r.MoveToElement ();
496                         }
497                         if (!r.IsEmptyElement) {
498                                 r.Read ();
499                                 e.ReadContentFrom (r, options);
500                                 r.ReadEndElement ();
501                                 e.explicit_is_empty = false;
502                         } else {
503                                 e.explicit_is_empty = true;
504                                 r.Read ();
505                         }
506                         return e;
507                 }
508
509                 public static XElement Parse (string text)
510                 {
511                         return Parse (text, LoadOptions.None);
512                 }
513
514                 public static XElement Parse (string text, LoadOptions options)
515                 {
516                         return Load (new StringReader (text), options);
517                 }
518
519                 public void RemoveAll ()
520                 {
521                         RemoveAttributes ();
522                         RemoveNodes ();
523                 }
524
525                 public void RemoveAttributes ()
526                 {
527                         while (attr_first != null)
528                                 attr_last.Remove ();
529                 }
530
531                 public void Save (string fileName)
532                 {
533                         Save (fileName, SaveOptions.None);
534                 }
535
536                 public void Save (string fileName, SaveOptions options)
537                 {
538                         XmlWriterSettings s = new XmlWriterSettings ();
539
540                         if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
541                                 s.Indent = true;
542 #if NET_4_0 || MOONLIGHT || MOBILE
543                         if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
544                                 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
545 #endif
546                         using (XmlWriter w = XmlWriter.Create (fileName, s)) {
547                                 Save (w);
548                         }
549                 }
550
551                 public void Save (TextWriter textWriter)
552                 {
553                         Save (textWriter, SaveOptions.None);
554                 }
555
556                 public void Save (TextWriter textWriter, SaveOptions options)
557                 {
558                         XmlWriterSettings s = new XmlWriterSettings ();
559                         
560                         if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
561                                 s.Indent = true;
562 #if NET_4_0 || MOONLIGHT || MOBILE
563                         if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
564                                 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
565 #endif
566                         using (XmlWriter w = XmlWriter.Create (textWriter, s)) {
567                                 Save (w);
568                         }
569                 }
570
571                 public void Save (XmlWriter writer)
572                 {
573                         WriteTo (writer);
574                 }
575
576 #if NET_4_0 || MOONLIGHT || MOBILE
577                 public void Save (Stream stream)
578                 {
579                         Save (stream, SaveOptions.None);
580                 }
581
582                 public void Save (Stream stream, SaveOptions options)
583                 {
584                         XmlWriterSettings s = new XmlWriterSettings ();
585                         if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
586                                 s.Indent = true;
587                         if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
588                                 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
589
590                         using (var writer = XmlWriter.Create (stream, s)){
591                                 Save (writer);
592                         }
593                 }
594 #endif
595                 public IEnumerable <XElement> AncestorsAndSelf ()
596                 {
597                         return GetAncestorList (null, true);
598                 }
599
600                 public IEnumerable <XElement> AncestorsAndSelf (XName name)
601                 {
602                         return GetAncestorList (name, true);
603                 }
604
605                 public IEnumerable <XElement> DescendantsAndSelf ()
606                 {
607                         List <XElement> list = new List <XElement> ();
608                         list.Add (this);
609                         list.AddRange (Descendants ());
610                         return list;
611                 }
612
613                 public IEnumerable <XElement> DescendantsAndSelf (XName name)
614                 {
615                         List <XElement> list = new List <XElement> ();
616                         if (name == this.name)
617                                 list.Add (this);
618                         list.AddRange (Descendants (name));
619                         return list;
620                 }
621
622                 public IEnumerable <XNode> DescendantNodesAndSelf ()
623                 {
624                         yield return this;
625                         foreach (XNode node in DescendantNodes ())
626                                 yield return node;
627                 }
628
629                 public void SetAttributeValue (XName name, object value)
630                 {
631                         XAttribute a = Attribute (name);
632                         if (value == null) {
633                                 if (a != null)
634                                         a.Remove ();
635                         } else {
636                                 if (a == null) {
637                                         SetAttributeObject (new XAttribute (name, value));
638                                 }
639                                 else
640                                         a.Value = XUtil.ToString (value);
641                         }
642                 }
643
644                 void SetAttributeObject (XAttribute a)
645                 {
646                         OnAddingObject (a);
647                         a = (XAttribute) XUtil.GetDetachedObject (a);
648                         a.SetOwner (this);
649                         if (attr_first == null) {
650                                 attr_first = a;
651                                 attr_last = a;
652                         } else {
653                                 attr_last.NextAttribute = a;
654                                 a.PreviousAttribute = attr_last;
655                                 attr_last = a;
656                         }
657                         OnAddedObject (a);
658                 }
659
660                 string LookupPrefix (string ns, XmlWriter w)
661                 {
662                         string prefix = ns.Length > 0 ? GetPrefixOfNamespace (ns) ?? w.LookupPrefix (ns) : String.Empty;
663                         foreach (XAttribute a in Attributes ()) {
664                                 if (a.IsNamespaceDeclaration && a.Value == ns) {
665                                         if (a.Name.Namespace == XNamespace.Xmlns)
666                                                 prefix = a.Name.LocalName;
667                                         // otherwise xmlns="..."
668                                         break;
669                                 }
670                         }
671                         return prefix;
672                 }
673                 
674                 static string CreateDummyNamespace (ref int createdNS, IEnumerable<XAttribute> atts, bool isAttr)
675                 {
676                         if (!isAttr && atts.All (a => a.Name.LocalName != "xmlns" || a.Name.NamespaceName == XNamespace.Xmlns.NamespaceName))
677                                 return String.Empty;
678                         string p = null;
679                         do {
680                                 p = "p" + (++createdNS);
681                                 // check conflict
682                                 if (atts.All (a => a.Name.LocalName != p || a.Name.NamespaceName == XNamespace.Xmlns.NamespaceName))
683                                         break;
684                         } while (true);
685                         return p;
686                 }
687
688                 public override void WriteTo (XmlWriter writer)
689                 {
690                         // some people expect the same prefix output as in input,
691                         // in the loss of performance... see bug #466423.
692                         string prefix = LookupPrefix (name.NamespaceName, writer);
693                         int createdNS = 0;
694                         if (prefix == null)
695                                 prefix = CreateDummyNamespace (ref createdNS, Attributes (), false);
696
697                         writer.WriteStartElement (prefix, name.LocalName, name.Namespace.NamespaceName);
698
699                         foreach (XAttribute a in Attributes ()) {
700                                 if (a.IsNamespaceDeclaration) {
701                                         if (a.Name.Namespace == XNamespace.Xmlns)
702                                                 writer.WriteAttributeString ("xmlns", a.Name.LocalName, XNamespace.Xmlns.NamespaceName, a.Value);
703                                         else
704                                                 writer.WriteAttributeString ("xmlns", a.Value);
705                                 } else {
706                                         string apfix = LookupPrefix (a.Name.NamespaceName, writer);
707                                         if (apfix == null)
708                                                 apfix = CreateDummyNamespace (ref createdNS, Attributes (), true);
709                                         writer.WriteAttributeString (apfix, a.Name.LocalName, a.Name.Namespace.NamespaceName, a.Value);
710                                 }
711                         }
712
713                         foreach (XNode node in Nodes ())
714                                 node.WriteTo (writer);
715
716                         if (explicit_is_empty)
717                                 writer.WriteEndElement ();
718                         else
719                                 writer.WriteFullEndElement ();
720                 }
721
722                 public XNamespace GetDefaultNamespace ()
723                 {
724                         for (XElement el = this; el != null; el = el.Parent)
725                                 foreach (XAttribute a in el.Attributes ())
726                                         if (a.IsNamespaceDeclaration && a.Name.Namespace == XNamespace.None)
727                                                 return XNamespace.Get (a.Value);
728                         return XNamespace.None; // nothing is declared.
729                 }
730
731                 public XNamespace GetNamespaceOfPrefix (string prefix)
732                 {
733                         for (XElement el = this; el != null; el = el.Parent)
734                                 foreach (XAttribute a in el.Attributes ())
735                                         if (a.IsNamespaceDeclaration && (prefix.Length == 0 && a.Name.LocalName == "xmlns" || a.Name.LocalName == prefix))
736                                                 return XNamespace.Get (a.Value);
737                         return XNamespace.None; // nothing is declared.
738                 }
739
740                 public string GetPrefixOfNamespace (XNamespace ns)
741                 {
742                         foreach (string prefix in GetPrefixOfNamespaceCore (ns))
743                                 if (GetNamespaceOfPrefix (prefix) == ns)
744                                         return prefix;
745                         return null; // nothing is declared
746                 }
747                 
748                 IEnumerable<string> GetPrefixOfNamespaceCore (XNamespace ns)
749                 {
750                         for (XElement el = this; el != null; el = el.Parent)
751                                 foreach (XAttribute a in el.Attributes ())
752                                         if (a.IsNamespaceDeclaration && a.Value == ns.NamespaceName)
753                                                 yield return a.Name.Namespace == XNamespace.None ? String.Empty : a.Name.LocalName;
754                 }
755
756                 public void ReplaceAll (object content)
757                 {
758                         RemoveNodes ();
759                         Add (content);
760                 }
761
762                 public void ReplaceAll (params object [] content)
763                 {
764                         RemoveNodes ();
765                         Add (content);
766                 }
767
768                 public void ReplaceAttributes (object content)
769                 {
770                         RemoveAttributes ();
771                         Add (content);
772                 }
773
774                 public void ReplaceAttributes (params object [] content)
775                 {
776                         RemoveAttributes ();
777                         Add (content);
778                 }
779
780                 public void SetElementValue (XName name, object value)
781                 {
782                         var element = Element (name);
783                         if (element == null && value != null) {
784                                 Add (new XElement (name, value));
785                         } else if (element != null && value == null) {
786                                 element.Remove ();
787                         } else
788                                 element.SetValue (value);
789                 }
790
791                 public void SetValue (object value)
792                 {
793                         if (value == null)
794                                 throw new ArgumentNullException ("value");
795                         if (value is XAttribute || value is XDocument || value is XDeclaration || value is XDocumentType)
796                                 throw new ArgumentException (String.Format ("Node type {0} is not allowed as element value", value.GetType ()));
797                         RemoveNodes ();
798                         foreach (object o in XUtil.ExpandArray (value))
799                                 Add (o);
800                 }
801
802                 internal override bool OnAddingObject (object o, bool rejectAttribute, XNode refNode, bool addFirst)
803                 {
804                         if (o is XDocument || o is XDocumentType || o is XDeclaration || (rejectAttribute && o is XAttribute))
805                                 throw new ArgumentException (String.Format ("A node of type {0} cannot be added as a content", o.GetType ()));
806
807                         XAttribute a = o as XAttribute;
808                         if (a != null) {
809                                 foreach (XAttribute ia in Attributes ())
810                                         if (a.Name == ia.Name)
811                                                 throw new InvalidOperationException (String.Format ("Duplicate attribute: {0}", a.Name));
812                                 SetAttributeObject (a);
813                                 return true;
814                         }
815                         else if (o is string && refNode is XText) {
816                                 ((XText) refNode).Value += o as string;
817                                 return true;
818                         }
819                         else
820                                 return false;
821                 }
822
823                 void IXmlSerializable.WriteXml (XmlWriter writer)
824                 {
825                         Save (writer);
826                 }
827
828                 void IXmlSerializable.ReadXml (XmlReader reader)
829                 {
830                         ReadContentFrom (reader, LoadOptions.None);
831                 }
832
833                 XmlSchema IXmlSerializable.GetSchema ()
834                 {
835                         return null;
836                 }
837         }
838 }