【问题标题】:Remove Xml declaration from web service response从 Web 服务响应中删除 Xml 声明
【发布时间】:2012-10-16 21:59:00
【问题描述】:

我有以下网络服务。输出文件顶部有 XML 声明 <?xml version="1.0" encoding="utf-8"?>。我需要摆脱它才能让我的移动应用程序正常工作。我该怎么做?

[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;
    }

编辑 1:我尝试返回 Xml 元素而不是文档,但它也不起作用。我仍然看到声明。

 [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;
        }

编辑 2:我能够通过使用 HttpHandler 来解决这个问题。请参阅下面的答案。

【问题讨论】:

  • 为什么需要删除声明? XmlDocument 应该能够读取它。您如何在移动应用中使用 Xml?
  • 这是我在 Windows Metro App 部分发布的链接问题,它回答了您的问题 - stackoverflow.com/questions/12905686/…。简而言之,应用程序无法正常使用 XML 声明。
  • 你能返回 XmlNode(或者实际上是 XmlElement)而不是 XmlDocument 吗?你会返回 xml.DocumentElement.
  • 我刚刚尝试了您的建议(XmlNode 和 XmlElement),但我仍然在响应中看到声明。似乎是在运行时动态添加声明。

标签: c# xml web-services


【解决方案1】:

以下方法将在没有声明的情况下将对象输出到 XML。关键部分是 XmlWriterSettings 类。见下文。

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());
        }

虽然在处理类对象时使用此方法,但在处理字符串时适用相同的原则。关键部分是 XmlWriterSettings 类,并且可能(尽管您的帖子没有提到) XmlSerializerNamespaces 类。

该方法将返回一个没有 xml 声明且没有命名空间的字符串,这非常适合我需要使用的 Web 服务片段。

--编辑--

以下短程序打印没有声明和标签的所有内容:

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());
}

【讨论】:

  • Web 服务在我调用它时仍会添加 XML 声明。请看我对上面@AntLaC 回答的回复。
  • 我明天必须研究一下 - 我的所有代码都在工作:/
  • 它可能会正确打印,但是当您将它放入 Web 服务方法并调用它时,XML 声明会在运行时动态添加。在您的示例中,returnedXml 变量中的值最终将与fragment 变量中的值相同。创建一个简单的 Web 服务,将您的代码复制到其中,然后通过浏览器调用该服务。然后右键单击并查看源代码或检查 Fiddler 中的 Raw 选项卡。您将看到 XML 声明。
  • @tempid 我想这两个变量最终是相同的。您是否可以控制 Web 服务本身?
  • 是的,我愿意。你想让我试试吗?
【解决方案2】:

不返回 XmlDocument 对象,而是返回字符串 return xml.InnerXml;

【讨论】:

  • 那行不通。我仍然在响应中看到声明,它还将整个内容包装在 string 元素中。
【解决方案3】:
【解决方案4】:

我能够通过摆脱 Web 服务并改用 HttpHandler 来获得我正在寻找的输出。这是代码-

     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);
            }
        }

【讨论】:

    【解决方案5】:

    有效的 XML 文档将始终将此作为文档的第一行。如果没有这一行,您将无法创建 XML 文档,即使您这样做了,这也不是有效的 XML。

    你为什么要这样做?

    如果您想将其转换为字符串...在您的 WebMethod 中将其从 XmlDocument 更改为字符串...使用 C# 删除第一行并将其作为字符串返回。

    [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; 
    } 
    

    不过,我的建议是保留第一行。

    【讨论】:

    • 我需要返回 XML 的一个片段,而不是整个文档。我已经更改了方法(请参阅我的问题中的编辑 1)以返回 XElement 而不是 XDocument 但它仍然添加了声明。我的 Metro 应用程序需要没有声明的 XML。我没有使用 MVC。这是一个 C#/XAML 项目。我尝试将其转换为字符串 (Xml.InnerXml),但应用程序不喜欢它。它需要 text/xml 而不是 text/plain 的响应。
    • 在您的移动应用程序中将 text/plain 转换为 text/xml
    • 恐怕 Windows Metro 框架没有给我那种转换响应类型的灵活性。它只需要服务的 URL,而不需要其他任何东西。不过,很棒的建议!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多