1

I have the following web service. The output has the XML declaration <?xml version="1.0" encoding="utf-8"?> at the top of the file. I need to get rid of it for my mobile app to work correctly. How do I do it?

[WebMethod]
    public XmlDocument GetTileData(string user)
    {
        var xml = new XmlDocument();
        xml.LoadXml(string.Format(@"<tile>
                                  <visual>
                                    <binding template='TileWideSmallImageAndText02'>
                                      <image id='1' src='http://server/images/{0}_wide.png'/>
                                      <text id='1'>Custom Field : {1}/text>
                                      <text id='2'>Custom Field : {2}</text>
                                      <text id='3'>Custom Field : {3}</text>
                                    </binding>
                                    <binding template='TileSquarePeekImageAndText01'>
                                      <image id='1' src='http://server/images/{0}_square.png'/>
                                      <text id='1'>Custom Field</text>
                                      <text id='2'>{1}</text>
                                    </binding>    
                                  </visual>
                                </tile>", value1, value2, value3, value4));

        return xml;
    }

Edit 1: I tried to return the Xml Element instead of the document, but it's not working either. I still see the declaration.

 [WebMethod]
        public XElement GetTileData(string user)
        {
            var xml = XDocument.Parse(string.Format(@"<tile>
                                      <visual>
                                        <binding template='TileWideSmallImageAndText02'>
                                          <image id='1' src='http://server/images/{0}_wide.png'/>
                                          <text id='1'>Custom Field : {1}/text>
                                          <text id='2'>Custom Field : {2}</text>
                                          <text id='3'>Custom Field : {3}</text>
                                        </binding>
                                        <binding template='TileSquarePeekImageAndText01'>
                                          <image id='1' src='http://server/images/{0}_square.png'/>
                                          <text id='1'>Custom Field</text>
                                          <text id='2'>{1}</text>
                                        </binding>    
                                      </visual>
                                    </tile>", value1, value2, value3, value4));

            return xml.Root;
        }

Edit 2: I was able to get around this issue by using a HttpHandler. See my answer below.

tempid
  • 7,838
  • 28
  • 71
  • 101
  • 1
    Why do you need to remove the declaration? XmlDocument is should be able to read it. How do you consume the Xml in your mobile app? – Pawel Oct 16 '12 at 22:06
  • Here's my linked question posted in Windows Metro App section which answers your question - http://stackoverflow.com/questions/12905686/update-tile-notifcation-with-xml-returned-by-web-service. In a nutshell, the app is not working correctly with the XML declaration. – tempid Oct 16 '12 at 22:10
  • Can you return XmlNode (or actually XmlElement) instead of XmlDocument? you would return xml.DocumentElement. – Pawel Oct 16 '12 at 22:17
  • I just tried your suggestion (both XmlNode and XmlElement) but I still see the declaration in the response. It seems to add the declaration dynamically at runtime. – tempid Oct 16 '12 at 22:19

5 Answers5

1

The following method will output an object to XML without the declaration. The key part is the XmlWriterSettings class. See below.

public static string SerializeToString(object obj)
        {
            var serializer = new XmlSerializer(obj.GetType());
            var ns = new XmlSerializerNamespaces();
            ns.Add("", "");
            var ms = new MemoryStream();
            //the following line omits the xml declaration
            var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = new UnicodeEncoding(false, false) };
            var writer = XmlWriter.Create(ms, settings);
            serializer.Serialize(writer, obj, ns);
            return Encoding.Unicode.GetString(ms.ToArray());
        }

Whereas this method is used when working with class objects, the same principals apply when working with strings. The key parts are the XmlWriterSettings class, and likely (although your post doesn't mention it) the XmlSerializerNamespaces class.

The method will return a string with no xml declaration and no namespaces, which works perfectly for the web service fragments I need to use.

--Edit--

the following short program prints everything without the declaration and without tags:

var xml = new XmlDocument();
    var fragment = @"<tile>
                          <visual>
                            <binding template='TileWideSmallImageAndText02'>
                              <image id='1' src='http://server/images/{0}_wide.png'/>
                              <text id='1'>Custom Field : {1}/text>
                              <text id='2'>Custom Field : {2}</text>
                              <text id='3'>Custom Field : {3}</text>
                            </binding>
                            <binding template='TileSquarePeekImageAndText01'>
                              <image id='1' src='http://server/images/{0}_square.png'/>
                              <text id='1'>Custom Field</text>
                              <text id='2'>{1}</text>
                            </binding>    
                          </visual>
                        </tile>";

   var returnedXml = SerializeToString(fragment);
   returnedXml = returnedXml.Replace("<string>", "");
   returnedXml = returnedXml.Replace("</string>", "");
    Console.WriteLine(returnedXml);
}

public static string SerializeToString(string obj)
{
    var serializer = new XmlSerializer(obj.GetType());
    var ns = new XmlSerializerNamespaces();
    ns.Add("", "");
    var ms = new MemoryStream();
    //the following line omits the xml declaration
    var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = new UnicodeEncoding(false, false) };
    var writer = XmlWriter.Create(ms, settings);
    serializer.Serialize(writer, obj, ns);
    return Encoding.Unicode.GetString(ms.ToArray());
}
Robert H
  • 11,520
  • 18
  • 68
  • 110
  • The web service still adds the XML declaration when I invoke it. Please see me response to @AntLaC's answer above. – tempid Oct 16 '12 at 23:20
  • I will have to look into it tomorrow - all my code is at work :/ – Robert H Oct 16 '12 at 23:29
  • It might print correctly, but when you put this in a web service method and invoke it, the XML declaration gets added dynamically at runtime. The value in the `returnedXml` variable in your example will end up being the same as the value in the `fragment` variable. Create a simple webservice, copy your code in it, and invoke the service via browser. Then right-click and view the source or check the Raw tab in Fiddler. You'll see the XML declaration. – tempid Oct 16 '12 at 23:52
  • @tempid I suppose the two vars are the same in the end. Do you have control of the web service itself? – Robert H Oct 16 '12 at 23:55
  • Yes, I do. Do you want me to try something? – tempid Oct 17 '12 at 00:02
0

Instead of returning an XmlDocument object, return a string return xml.InnerXml;

AntLaC
  • 1,215
  • 10
  • 22
  • That didn't work. I still see the declaration in the response and it also wraps the whole thing in a `string` element. – tempid Oct 16 '12 at 22:04
0

I was able to get the output I'm looking for by getting rid of the web service and using a HttpHandler instead. Here's the code -

     public class Handler1 : IHttpHandler
        {        
            public void ProcessRequest(HttpContext context)
            {
               var xml= @"<tile>
                      <visual>
                        <binding template='TileWideSmallImageAndText02'>
                          <image id='1' src='http://server/images/{0}_wide.png'/>
                          <text id='1'>Custom Field : {1}/text>
                          <text id='2'>Custom Field : {2}</text>
                          <text id='3'>Custom Field : {3}</text>
                        </binding>
                        <binding template='TileSquarePeekImageAndText01'>
                          <image id='1' src='http://server/images/{0}_square.png'/>
                          <text id='1'>Custom Field</text>
                          <text id='2'>{1}</text>
                        </binding>    
                      </visual>
                    </tile>";

               context.Response.ContentType = "text/xml";
               context.Response.Write(xml);
            }
        }
tempid
  • 7,838
  • 28
  • 71
  • 101
-1

A Valid XML Document will always have this as the first line of your document. There is no way you can create a XML document without this line and even if you do then this is not a valid XML.

Why do you want to do this?

If you want to do it convert it to a string... in your WebMethod change it from XmlDocument to string... using C# remove the first line and return that as a string.

[WebMethod] 
public string GetTileData(string user) 
{ 
    string xml = string.Format(@"<tile> 
                              <visual> 
                                <binding template='TileWideSmallImageAndText02'> 
                                  <image id='1' src='http://server/images/{0}_wide.png'/> 
                                  <text id='1'>Custom Field : {1}/text> 
                                  <text id='2'>Custom Field : {2}</text> 
                                  <text id='3'>Custom Field : {3}</text> 
                                </binding> 
                                <binding template='TileSquarePeekImageAndText01'> 
                                  <image id='1' src='http://server/images/{0}_square.png'/> 
                                  <text id='1'>Custom Field</text> 
                                  <text id='2'>{1}</text> 
                                </binding>     
                              </visual> 
                            </tile>", value1, value2, value3, value4); 

    return xml; 
} 

My suggestion however is to keep this first line in there.

kevin c
  • 795
  • 1
  • 14
  • 29
  • I need to return a fragment of the XML, not the whole document. I've made changes to the method (please refer to Edit 1 in my question) to return `XElement` instead of `XDocument` but it still adds the declaration. My Metro app needs the XML without the declaration. I'm not using MVC. This is a C#/XAML project. I tried converting it to a string (Xml.InnerXml), but the app doesn't like it. It needs the response in text/xml and not text/plain. – tempid Oct 16 '12 at 22:45
  • In your mobile app convert the text/plain to text/xml – kevin c Oct 16 '12 at 22:48
  • I'm afraid the Windows Metro framework doesn't give me that flexibility to convert the response type. It only takes the URL of the service and nothing else. Great suggestion, though! – tempid Oct 16 '12 at 22:55