5 // Copyright 2007 Novell (http://www.novell.com)
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:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
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.
28 using System.Collections;
29 using System.Collections.Generic;
33 using System.Xml.Schema;
34 using System.Xml.Serialization;
36 namespace System.Xml.Linq
38 public class XDocument : XContainer
46 public XDocument (params object [] content)
51 public XDocument (XDeclaration declaration, params object [] content)
53 Declaration = declaration;
57 public XDocument (XDocument other)
59 foreach (object o in other.Nodes ())
60 Add (XUtil.Clone (o));
63 public XDeclaration Declaration {
64 get { return xmldecl; }
65 set { xmldecl = value; }
68 public XDocumentType DocumentType {
70 foreach (object o in Nodes ())
71 if (o is XDocumentType)
72 return (XDocumentType) o;
77 public override XmlNodeType NodeType {
78 get { return XmlNodeType.Document; }
81 public XElement Root {
83 foreach (object o in Nodes ())
90 public static XDocument Load (string uri)
92 return Load (uri, LoadOptions.None);
95 public static XDocument Load (string uri, LoadOptions options)
97 XmlReaderSettings s = new XmlReaderSettings ();
98 s.ProhibitDtd = false; // see XNodeNavigatorTest.MoveToId().
99 s.IgnoreWhitespace = (options & LoadOptions.PreserveWhitespace) == 0;
100 using (XmlReader r = XmlReader.Create (uri, s)) {
101 return LoadCore (r, options);
105 public static XDocument Load (Stream stream)
107 return Load (new StreamReader (stream), LoadOptions.None);
110 public static XDocument Load (Stream stream, LoadOptions options)
112 return Load (new StreamReader (stream), options);
115 public static XDocument Load (TextReader textReader)
117 return Load (textReader, LoadOptions.None);
120 public static XDocument Load (TextReader textReader, LoadOptions options)
122 XmlReaderSettings s = new XmlReaderSettings ();
123 s.ProhibitDtd = false; // see XNodeNavigatorTest.MoveToId().
124 s.IgnoreWhitespace = (options & LoadOptions.PreserveWhitespace) == 0;
125 using (XmlReader r = XmlReader.Create (textReader, s)) {
126 return LoadCore (r, options);
130 public static XDocument Load (XmlReader reader)
132 return Load (reader, LoadOptions.None);
135 public static XDocument Load (XmlReader reader, LoadOptions options)
137 XmlReaderSettings s = reader.Settings != null ? reader.Settings.Clone () : new XmlReaderSettings ();
138 s.IgnoreWhitespace = (options & LoadOptions.PreserveWhitespace) == 0;
139 using (XmlReader r = XmlReader.Create (reader, s)) {
140 return LoadCore (r, options);
144 static XDocument LoadCore (XmlReader reader, LoadOptions options)
146 XDocument doc = new XDocument ();
147 doc.ReadContent (reader, options);
151 void ReadContent (XmlReader reader, LoadOptions options)
153 if (reader.ReadState == ReadState.Initial)
155 this.FillLineInfoAndBaseUri (reader, options);
156 if (reader.NodeType == XmlNodeType.XmlDeclaration) {
157 Declaration = new XDeclaration (
158 reader.GetAttribute ("version"),
159 reader.GetAttribute ("encoding"),
160 reader.GetAttribute ("standalone"));
163 ReadContentFrom (reader, options);
165 throw new InvalidOperationException ("The document element is missing.");
168 static void ValidateWhitespace (string s)
170 for (int i = 0; i < s.Length; i++)
172 case ' ': case '\t': case '\n': case '\r':
175 throw new ArgumentException ("Non-whitespace text appears directly in the document.");
179 public static XDocument Parse (string text)
181 return Parse (text, LoadOptions.None);
184 public static XDocument Parse (string text, LoadOptions options)
186 return Load (new StringReader (text), options);
189 public void Save (string fileName)
191 Save (fileName, SaveOptions.None);
194 public void Save (string fileName, SaveOptions options)
196 XmlWriterSettings s = new XmlWriterSettings ();
197 if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
200 if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
201 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
204 using (XmlWriter w = XmlWriter.Create (fileName, s)) {
209 public void Save (TextWriter textWriter)
211 Save (textWriter, SaveOptions.None);
214 public void Save (TextWriter textWriter, SaveOptions options)
216 XmlWriterSettings s = new XmlWriterSettings ();
217 if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
220 if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
221 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
223 using (XmlWriter w = XmlWriter.Create (textWriter, s)) {
228 public void Save (XmlWriter writer)
233 public override void WriteTo (XmlWriter writer)
235 if (xmldecl != null && xmldecl.Standalone != null)
236 writer.WriteStartDocument (xmldecl.Standalone == "yes");
238 writer.WriteStartDocument ();
239 foreach (XNode node in Nodes ())
240 node.WriteTo (writer);
243 internal override bool OnAddingObject (object obj, bool rejectAttribute, XNode refNode, bool addFirst)
245 VerifyAddedNode (obj, addFirst);
249 void VerifyAddedNode (object node, bool addFirst)
252 throw new InvalidOperationException ("Only a node is allowed here");
255 ValidateWhitespace ((string) node);
257 ValidateWhitespace (((XText) node).Value);
258 else if (node is XDocumentType) {
259 if (DocumentType != null)
260 throw new InvalidOperationException ("There already is another document type declaration");
261 if (Root != null && !addFirst)
262 throw new InvalidOperationException ("A document type cannot be added after the document element");
264 else if (node is XElement) {
266 throw new InvalidOperationException ("There already is another document element");
267 if (DocumentType != null && addFirst)
268 throw new InvalidOperationException ("An element cannot be added before the document type declaration");
272 public void Save (Stream stream)
274 Save (stream, SaveOptions.None);
277 public void Save (Stream stream, SaveOptions options)
279 XmlWriterSettings s = new XmlWriterSettings ();
280 if ((options & SaveOptions.DisableFormatting) == SaveOptions.None)
282 if ((options & SaveOptions.OmitDuplicateNamespaces) == SaveOptions.OmitDuplicateNamespaces)
283 s.NamespaceHandling |= NamespaceHandling.OmitDuplicates;
285 using (var writer = XmlWriter.Create (stream, s)){