6

I have a web service that returns an xml string as results. The return string is in this format:

<ReturnValue>
   <ErrorNumber>0
</ErrorNumber>
<Message>my message</Message>
</ReturnValue>

The data that I want to insert into the "message" tag is a serialized version of a custom object. The serialized format of that object contains xml and namespace declarations post serialization. When that gets thrown into the "message" tag of my return xml string, XmlSpy says that it's not well-formed. How should I get rid of the namespace declarations, or is there a different way to imbed a serialized object into an xml string?

ganders
  • 7,285
  • 17
  • 66
  • 114
  • Redundant or new namespace declarations in the embedded data should not cause well-formedness errors, but embedding also the XML declaration inside your `` element probably will cause that. If removing the extra XML declaration doesn't fix the problem, then either your object serialization or web service return value produces malformed XML. – jasso Nov 29 '11 at 23:44

3 Answers3

8

Wrap the string in CDATA like so:

<![CDATA[your xml, which can be multi-line]]>

CDATA will inform a validator to treat the CDATA contents as ignored text. It's often the most expedient way to embed XML (or taggy non-XML content) as a string. You can run into problems if your embedded XML contains its own CDATA, but otherwise it's a simple fix.

phatfingers
  • 9,770
  • 3
  • 30
  • 44
7

Just make sure that your <Message> XML is encoded so that <, >, ", and & show up as &lt;, &gt;, &quot; and &amp;, respectively.

There are few built-in ways to encode the characters:

string message = System.Web.HttpUtility.HtmlEncode(serializedXml);

string message = System.Security.SecurityElement.Escape(serializedXml);
  • Using an XmlTextWriter to do the work for you
  • Use CDATA to wrap your XML

Also, this is probably a duplicate of:

  1. Best way to encode text data for XML
Community
  • 1
  • 1
Cᴏʀʏ
  • 105,112
  • 20
  • 162
  • 194
  • Would that be as easy as just doing a string.replace for all the different representations of those special xml characters? – ganders Nov 29 '11 at 20:09
0

Think of XML as a document not a string. Create a node named "wrapper", and store the content of your file in it as a Base64 encoded string. The results will look like this.

<ReturnValue>
  <ErrorNumber>0</ErrorNumber>
  <Message>my message</Message>
  <wrapper type="bin.base64">PD94bWwgdmVyc2lvbj0iMS4wIj8+PHhzbDpzdHlsZXNoZWV0IHZ
lcnNpb249IjEuMCIgeG1sbnM6eHNsPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L1hTTC9UcmFuc2Zvcm0
iIHhtbG5zOm1zeHNsPSJ1cm46c2NoZW1hcy1taWNyb3NvZnQtY29tOnhzbHQiPjx4c2w6b3V0cHV0IG1
ldGhvZD0ieG1sIiAvPjx4c2w6dGVtcGxhdGUgbWF0Y2g9Ii8iPjwveHNsOnRlbXBsYXRlPjwveHNsOnN
0eWxlc2hlZXQ+</wrapper>
</ReturnValue>

The following code shows how to add the wrapper, encode the content. Then it reverses the process to show that it all "works".

Using Base64 in XML has a number of other applications as well. For example embedding images, or other documents in XML content.

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

public class t
{

    static public string EncodeTo64(string toEncode) {
        byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
        string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);
        return returnValue;
    }

    static public string DecodeFrom64(string encodedData) {
        byte[] encodedDataAsBytes = System.Convert.FromBase64String(encodedData);
        string returnValue = System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
        return returnValue;
    }

    public static void Main() {
        try {
        //Create the XmlDocument.
        XmlDocument doc = new XmlDocument();
            doc.LoadXml( @"
            <ReturnValue>
            <ErrorNumber>0</ErrorNumber>
            <Message>my message</Message>
            </ReturnValue>
            ");

            XmlNode nodeMessage = doc.SelectSingleNode( "/ReturnValue/Message" );
            if( nodeMessage != null ) {
            XmlDocument docImport = new XmlDocument();
                docImport.Load( "docwithnamespace.xml" );

                // create a wrapper element for the file, then import and append it after <Message>
                XmlElement nodeWrapper = (XmlElement)doc.CreateElement( "wrapper" );
                nodeWrapper.SetAttribute( "type", "bin.base64" );

                nodeWrapper = (XmlElement)doc.ImportNode( nodeWrapper, true );
                XmlNode ndImport = nodeMessage.ParentNode.AppendChild( nodeWrapper.CloneNode( true ) );
                ndImport.InnerText = EncodeTo64( docImport.OuterXml );
                doc.Save( "wrapperadded.xml" );

                // Next, let's test un-doing the wrapping
                // Re-load the "wrapped" document
                XmlDocument docSaved = new XmlDocument();
                docSaved.Load( "wrapperadded.xml" );

                // Get the wrapped element, decode from base64 write to disk
                XmlNode node = doc.SelectSingleNode( "/ReturnValue/wrapper" );
                if( node != null ) {
                    // Load the content, and save as a new XML
                    XmlDocument docUnwrapped = new XmlDocument();
                    docUnwrapped.LoadXml( DecodeFrom64( node.InnerText ) );
                    docUnwrapped.Save( "unwrapped.xml" );
                    Console.WriteLine( "Eureka" );
                }
            }


        } catch( Exception e ) {
            Console.WriteLine(e.Message);
        }
    }
}
William Walseth
  • 2,803
  • 1
  • 23
  • 25