1

Currently, I have a code project to convert data from excel to xml and I am using XmlDocument to write xml file to run testcase in available software. But in that software when running xml it only receives.

<?xml version='1.0' encoding='utf-8'?>

When I use CreateXmlDeclaration function of XmlDocument

XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("'1.0", "'utf-8'", null);

My result -> <?xml version="1.0" encoding="utf-8"?>

I try modify it <?xml version="'1.0'" encoding="'utf-8'"?> and I get exception:

an unhandled exception of type 'System.ArgumentException' occurred in System.Xml.dll Wrong XML version information. The XML must match production "VersionNum ::= '1.' [0-9]+".

How can I use ' ' in CreateXmlDeclaration or use another API as an alternative to XmlDocument ?

burnsi
  • 6,194
  • 13
  • 17
  • 27
  • 2
    It is supposed to be double quotes, why are you trying to force it into single? – Crowcoder Jul 04 '22 at 16:11
  • 2
    In that case you have problems with all XML documents, because [the XML spec not only allows double quotes](https://www.w3.org/TR/2008/REC-xml-20081126), all the examples actually use double quotes and even mixed quotes – Panagiotis Kanavos Jul 04 '22 at 16:13
  • 1
    You should consider using the new DOM `System.Xml.Linq` and `XDocument` instead in general. Specifically you'd need to find the setting that controls the use of single quotes instead of double quotes when outputting the xml as text. For `XmlDocument` that requires using an `XmlTextWriter` with `QuoteChar` set to single quote. Note that will use single instead of double quotes for all attributes. – juharr Jul 04 '22 at 16:13
  • Hi @Crowcoder, because app of my firm using single quotes it is fixed and cannot be changed and it only accepts single quotes. I also don't want why. It's like it's by default. – Anh Hào Trần Jul 04 '22 at 16:19
  • @juharr, thank you, i consider use it. – Anh Hào Trần Jul 04 '22 at 16:25
  • A find/replace in Excel prior to export may work. – Solar Mike Jul 04 '22 at 16:25
  • Hi @SolarMike, just use single quotes and it not in the excel file, all data in excel use " " – Anh Hào Trần Jul 04 '22 at 16:33
  • 1
    1) `` is malformed. According to the [spec](https://www.w3.org/TR/REC-xml/#NT-VersionInfo) it should be `` or `` but never `"'1.0'"` (with both types of quote at once). Was that a typo in your question, or do you really want such malformed XML? – dbc Jul 04 '22 at 19:43
  • 2) Assuming you want ``, do you also want the single quote char used for attributes also? Or just for the XML declaration and nothing else? – dbc Jul 04 '22 at 19:43
  • More specifically, is this what you want? https://dotnetfiddle.net/YNx7Dq – dbc Jul 04 '22 at 19:55
  • For example you could do this https://dotnetfiddle.net/0HaYFA – Charlieface Jul 04 '22 at 20:06
  • Thank you everyone, I undertood and resolved a problem. – Anh Hào Trần Jul 05 '22 at 02:52

1 Answers1

0

You have a couple of issues here:

  1. There is no need to manually add an XML Declaration to an XmlDocument by calling CreateXmlDeclaration(). The XML Declaration will be written automatically using the current encoding when you call one of the overloads of XmlDocument.Save(). It will not be written when you inspect the value of OuterXml or call XmlDocument.WriteTo().

  2. When writing XML using XmlTextWriter you may control the quote character by setting XmlTextWriter.QuoteChar = '\''[1].

    Note that this property controls both the quote character used in the XML declaration, and the quote character used for attribute values.

    Note also that, while XmlTextWriter has been deprecated in favor of calling XmlWriter.Create(), there does not appear to be a way to set the quote character using XmlWriterSettings.

Thus, if you want to use a single quote character for both the XML declaration and attribute values, you can introduce the following extension method:

public static partial class XmlSerializationHelper
{
    public static string GetOuterXml(this XmlDocument doc, bool indent = true, char quoteChar = '"')
    {
        if (doc == null)
            return null;
        using (var textWriter = new StringWriterWithEncoding())
        {
            using (var xmlWriter = new XmlTextWriter(textWriter) { Formatting = indent ? Formatting.Indented : Formatting.None, QuoteChar = quoteChar })
            {
                doc.Save(xmlWriter);
            }
            return textWriter.ToString();
        }
    }
}

public sealed class StringWriterWithEncoding : StringWriter
{
    // From this answer https://stackoverflow.com/a/42584394/3744182
    // To https://stackoverflow.com/questions/42583299/xmlwriter-encoding-utf-8-using-stringwriter-in-c-sharp
    public StringWriterWithEncoding() : this(Encoding.UTF8) { }
    public StringWriterWithEncoding(Encoding encoding) => this.Encoding = encoding;
    public override Encoding Encoding { get; }
}

And, for the XML <foo Name="hello"><bar Id="101">var value</bar></foo>, the method doc.GetOuterXml(quoteChar : '\'') will generate:

<?xml version='1.0' encoding='utf-8'?>
<foo Name='hello'>
  <bar Id='101'>var value</bar>
</foo>

Demo fiddle #1 here.

Notice that the single quote character is used for both the XML declaration and attribute values. Your question is unclear, but if you need a single quote for the XML Declaration only and double quotes otherwise, you will need to subclass XmlTextWriter like so:

public static partial class XmlSerializationHelper
{
    public static string GetOuterXml(this XmlDocument doc, bool indent = true)
    {
        if (doc == null)
            return null;
        using (var textWriter = new StringWriterWithEncoding())
        {
            using (var xmlWriter = new CustomQuoteCharXmlTextWriter(textWriter) { Formatting = indent ? Formatting.Indented : Formatting.None })
            {
                doc.Save(xmlWriter);
            }
            return textWriter.ToString();
        }
    }
}

public class CustomQuoteCharXmlTextWriter : XmlTextWriter
{
    public CustomQuoteCharXmlTextWriter(Stream w, Encoding encoding) : base(w, encoding) => QuoteChar = '\'';
    public CustomQuoteCharXmlTextWriter(String filename, Encoding encoding) : base(filename, encoding) => QuoteChar = '\'';
    public CustomQuoteCharXmlTextWriter(TextWriter w) : base(w) => QuoteChar = '\'';
    
    public override void WriteStartDocument() 
    {
        base.WriteStartDocument();
        QuoteChar = '"';
    }
}

And now doc.GetOuterXml() will return:

<?xml version='1.0' encoding='utf-8'?>
<foo Name="hello">
  <bar Id="101">var value</bar>
</foo>

Demo fiddle #2 here.


[1] See this answer by Peter Ritchie to Can one force XMLWriter to write elements in single quotes?

dbc
  • 104,963
  • 20
  • 228
  • 340