Search code examples
c#memorystreamxmlwriter

Load XML String having escape characters


I have a string sMediaXML which resembles an XML fragment, except for the fact that it contains backslash escape characters. I am unable to load this string into an XmlDocument enabling me to check and see if an element exists etc... I need to keep the string format exactly as you see below because other code will be depending on it later on.

// sMediaXML = "<media><cd><burned value=\"true\" /></cd><vinyl><pressed value=\"true\" /></vinyl></media>"   

using System;
using System.IO;
using System.Text;
using System.Xml;

namespace xmlWriter_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = true;
            settings.ConformanceLevel = ConformanceLevel.Fragment;
            settings.CloseOutput = false;

            MemoryStream strm = new MemoryStream();

            using (XmlWriter writer = XmlWriter.Create(strm, settings))
            {
                writer.WriteStartElement("media");
                writer.WriteStartElement("cd");
                writer.WriteStartElement("burned");
                writer.WriteAttributeString("value", "true");
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteStartElement("vinyl");
                writer.WriteStartElement("pressed");
                writer.WriteAttributeString("value", "true");
                writer.WriteEndElement();
                writer.WriteEndElement();
                writer.WriteEndElement();
            }

            string sMediaXML = Encoding.UTF8.GetString((strm).ToArray());
            Boolean bNodeExists;

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(sMediaXML);

            if (xmlDoc.SelectSingleNode("/media/digital/@value").Value != null)
            {
                bNodeExists = true;
            }
            else
            {
                bNodeExists = false;
            }
        }
    }
}

Solution

  • You should try this:

    XmlWriterSettings settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    settings.ConformanceLevel = ConformanceLevel.Document;
    settings.CloseOutput = false;
    
    MemoryStream strm = new MemoryStream();
    
    using (XmlWriter writer = XmlWriter.Create(strm, settings))
    {
        writer.WriteStartElement("media");
        writer.WriteStartElement("cd");
        writer.WriteStartElement("burned");
        writer.WriteAttributeString("value", "true");
        writer.WriteEndElement();
        writer.WriteEndElement();
        writer.WriteStartElement("vinyl");
        writer.WriteStartElement("pressed");
        writer.WriteAttributeString("value", "true");
        writer.WriteEndElement();
        writer.WriteEndElement();
        writer.WriteEndElement();
    }
    
    string sMediaXML = Encoding.UTF8.GetString((strm).ToArray());
    Boolean bNodeExists;
    string _byteOrderMarkUtf8 = Encoding.UTF8.GetString(Encoding.UTF8.GetPreamble());
    if (sMediaXML.StartsWith(_byteOrderMarkUtf8))
    {
        sMediaXML = sMediaXML.Remove(0, _byteOrderMarkUtf8.Length);
    }
    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.LoadXml(sMediaXML);
    
    if (xmlDoc.SelectSingleNode("/media/cd/burned/@value").Value != null)
    {
        bNodeExists = true;
    }
    else
    {
        bNodeExists = false;
    }
    
    1. If you have an XML string that you want to load into a XDocument you should use LoadXml method not Load. The Load method is used when loading directly from disk or streams.
    2. The XDocument can not parse the xml string because it contains the UTF-8 byte specifying the order. More information here. There is an other option for this to work, to view it, check this SO question.
    3. The XPath query you have won't work anyway because you don't have any "digital" elements defined.