Search code examples
.netxmlxml-serializationxmlwriter

How to write boolean attribute (specified - not specified) with XmlWriter?


Is there any possible way to write an attribute without value:

<element specified/>

I believe I can do it with:

writer.WriteRaw("<element specified/>")

But is there is any way to do it with WriteAttributeString, WriteStartAttribute, WriteAttributes or other methods?


Solution

  • If you need to write old-style SGML structure, you may consider using HtmlTextWriter, or any of its descendants, like XhtmlTextWriter. Their original intentions were for use in ASP.NET, but since they derive from TextWriter, they should be usable in other scenario's as well.

    If you need even more flexibility, it would be nice to have an SGMLWriter. Unfortunately, I was only able to find an SGMLReader.

    Edit

    You can create an XmlWriter that writes valid HTML which isn't valid XML, as in HTML 3.2 or 4.0. You can do so by overwriting OutputMethod using reflection (it is a read-only property, it won't let you do it otherwise, as far as I found). Example:

    XmlWriterSettings settings = new XmlWriterSettings();
    
    // Use reflection, not that you need GetMethod, not GetProperty
    MethodInfo propOutputMethod = settings.GetType().GetMethod("set_OutputMethod", 
        BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod);
    propOutputMethod.Invoke(settings, new object[] { XmlOutputMethod.Html });
    
    // check value, it should contain XmlOutputMethod.Html now
    var outputMethod = settings.OutputMethod;
    
    // continue as you used to do
    StringBuilder builder = new StringBuilder();
    XmlWriter writer = XmlWriter.Create(builder, settings);
    writer.WriteStartDocument();
    writer.WriteStartElement("html");
    writer.WriteStartElement("input");
    writer.WriteAttributeString("ismap", "value");
    writer.WriteEndElement();
    writer.WriteElementString("br", null);
    writer.WriteElementString("img", null);
    writer.WriteEndElement();
    writer.WriteEndDocument();
    writer.Flush();
    
    // variable output will now contain "<html><input ismap><br><img></html>"
    string output = builder.ToString();
    

    Important note: this will only work for predefined attributes and tags. As far as I know, this can only be done with the ones defined in the HTML 4.0 specification as boolean or as tag not requiring closing (br, img, hr etc).

    In addition, if you try to create illegal combinations, it will use standard syntax. It is not possible to force a boolean attribute without ="". I.e., this works: <input ismap>, this doesn't <inputs ismap=""></inputs>.