public override void WriteEndAttribute () { if (state != WriteState.Attribute) throw StateError ("End of attribute"); if (writer.Wrapped == preserver) { writer = writer.PreviousWrapper ?? new TextWriterWrapper (source, this); string value = preserver.ToString (); if (is_preserved_xmlns) { if (preserved_name.Length > 0 && value.Length == 0) throw ArgumentError ("Non-empty prefix must be mapped to non-empty namespace URI."); string existing = nsmanager.LookupNamespace (preserved_name, false); explicit_nsdecls.Add (preserved_name); if (open_count > 0) { if (v2 && elements [open_count - 1].Prefix == preserved_name && elements [open_count - 1].NS != value) throw new XmlException (String.Format ("Cannot redefine the namespace for prefix '{0}' used at current element", preserved_name)); if (elements [open_count - 1].NS != String.Empty || elements [open_count - 1].Prefix != preserved_name) { if (existing != value) nsmanager.AddNamespace (preserved_name, value); } } } else { switch (preserved_name) { case "lang": if (open_count > 0) elements [open_count - 1].XmlLang = value; break; case "space": switch (value) { case "default": if (open_count > 0) elements [open_count - 1].XmlSpace = XmlSpace.Default; break; case "preserve": if (open_count > 0) elements [open_count - 1].XmlSpace = XmlSpace.Preserve; break; default: throw ArgumentError ("Invalid value for xml:space."); } break; } } writer.Write (value); } writer.Write (formatSettings.QuoteChar); if (writer.InBlock) { writer.MarkBlockEnd (); if (writer.Column > TextPolicy.FileWidth) { WriteIndentAttribute (); writer.WriteBlock (true); writer.AttributesPerLine++; } else { writer.WriteBlock (false); } } state = WriteState.Element; }
public TextWriterWrapper (TextWriter wrapped, XmlFormatterWriter formatter, TextWriterWrapper currentWriter) : this (wrapped, formatter) { PreviousWrapper = currentWriter; }
// Attribute public override void WriteStartAttribute ( string prefix, string localName, string namespaceUri) { // LAMESPEC: this violates the expected behavior of // this method, as it incorrectly allows unbalanced // output of attributes. Microfot changes description // on its behavior at their will, regardless of // ECMA description. if (state == WriteState.Attribute) WriteEndAttribute (); if (state != WriteState.Element && state != WriteState.Start) throw StateError ("Attribute"); if ((object) prefix == null) prefix = String.Empty; // For xmlns URI, prefix is forced to be "xmlns" bool isNSDecl = false; if (namespaceUri == XmlnsNamespace) { isNSDecl = true; if (prefix.Length == 0 && localName != "xmlns") prefix = "xmlns"; } else isNSDecl = (prefix == "xmlns" || localName == "xmlns" && prefix.Length == 0); if (namespaces) { // MS implementation is pretty hacky here. // Regardless of namespace URI it is regarded // as NS URI for "xml". if (prefix == "xml") namespaceUri = XmlNamespace; // infer namespace URI. else if ((object) namespaceUri == null) { if (isNSDecl) namespaceUri = XmlnsNamespace; else namespaceUri = String.Empty; } // It is silly design - null namespace with // "xmlns" are allowed (for namespace-less // output; while there is Namespaces property) // On the other hand, namespace "" is not // allowed. if (isNSDecl && namespaceUri != XmlnsNamespace) throw ArgumentError (String.Format ("The 'xmlns' attribute is bound to the reserved namespace '{0}'", XmlnsNamespace)); // If namespace URI is empty, then either prefix // must be empty as well, or there is an // existing namespace mapping for the prefix. if (prefix.Length > 0 && namespaceUri.Length == 0) { namespaceUri = nsmanager.LookupNamespace (prefix, false); if (namespaceUri == null || namespaceUri.Length == 0) throw ArgumentError ("Namespace URI must not be null when prefix is not an empty string."); } // Dive into extremely complex procedure. if (!isNSDecl && namespaceUri.Length > 0) prefix = DetermineAttributePrefix ( prefix, localName, namespaceUri); } writer.AttributesPerLine++; if (formatSettings.WrapAttributes && writer.AttributesPerLine > 1) writer.MarkBlockStart (); if (formatSettings.AttributesInNewLine || writer.AttributesPerLine > formatSettings.MaxAttributesPerLine) { writer.MarkBlockEnd (); WriteIndentAttribute (); writer.AttributesPerLine = 1; } else if (state != WriteState.Start) writer.Write (' '); if (prefix.Length > 0) { writer.Write (prefix); writer.Write (':'); } writer.Write (localName); WriteAssignment (); writer.Write (formatSettings.QuoteChar); if (isNSDecl || prefix == "xml") { if (preserver == null) preserver = new StringWriter (); else preserver.GetStringBuilder ().Length = 0; writer = new TextWriterWrapper (preserver, this, writer); if (!isNSDecl) { is_preserved_xmlns = false; preserved_name = localName; } else { is_preserved_xmlns = true; preserved_name = localName == "xmlns" ? String.Empty : localName; } } state = WriteState.Attribute; }
void Initialize (TextWriter writer) { if (writer == null) throw new ArgumentNullException ("writer"); XmlNameTable name_table = new NameTable (); this.writer = new TextWriterWrapper (writer, this); if (writer is StreamWriter) base_stream = ((StreamWriter) writer).BaseStream; source = writer; nsmanager = new XmlNamespaceManager (name_table); newline = writer.NewLine; escaped_text_chars = newline_handling != NewLineHandling.None ? new char [] {'&', '<', '>', '\r', '\n'} : new char [] {'&', '<', '>'}; escaped_attr_chars = new char [] {'"', '&', '<', '>', '\r', '\n'}; }