XML反序列化仅适用于XML中包含命名空间。

11
我使用ServiceStack进行XML反序列化最简单的方法是,当XML包含命名空间时。然而,我接收到的XML没有包含命名空间。以下是最简单的可行示例:
[Serializable]
public class test
{

}

class Program
{
   static void Main(string[] args)
   {
       string xml="<test xmlns=\"http://schemas.datacontract.org/2004/07/\"></test>";
       var result = ServiceStack.Text.XmlSerializer.DeserializeFromString<test>(xml);
   }
}

然而,那不是我想要的。我希望以下内容可以反序列化,因为这是我从多个服务获取的 XML:

string xml="<test></test>";

但是这会给我带来以下错误:
DeserializeDataContract: Error converting type: Error in line 1 position 7. 
Expecting element 'test' from namespace 
'http://schemas.datacontract.org/2004/07/'.. 
Encountered 'Element'  with name 'test', namespace ''.

我尝试过:

[Serializable]
[XmlRoot("test", Namespace = "")]
public class test

我无法创建一个新的Serializer,因为ServiceStack.Text.XmlSerializer是静态的。我需要选择Microsoft XmlSerializer或ServiceStack(不可以两者兼用)。这意味着:如果我无法让这个简单的例子工作,我就需要跳过ServiceStack包中非常有用的部分。我最不想做的事情就是在传入的xml中注入一些虚假的命名空间。
1个回答

27

ServiceStack使用.NET的Xml DataContractSerializer来序列化XML,如果要删除命名空间,您需要使用以下方式将命名空间设置为空字符串:

[DataContract(Namespace="")]
public class test { ... }

然后你将需要使用[DataMember]属性标记每个要序列化的属性。更好的选择是通过在Assembly.cs文件中添加程序集属性,为C#命名空间下的所有类型指定空命名空间,例如:

[assembly: System.Runtime.Serialization.ContractNamespace("", ClrNamespace = "YourNamespace")]
[assembly: ContractNamespace("", ClrNamespace = "MyServiceModel.DtoTypes")]

注意:您可以移除 [Serializable] 特性 - 它不被 ServiceStack 的任何序列化器使用。同时所有的 XmlSerializer 特性像 [XmlRoot] 都是无用的,因为 ServiceStack 使用 .NET 的 DataContractSerializer 而不是 Microsoft 较早的 XmlSerializer。


你没有编写自己的XML反序列化器,有什么原因吗?Microsoft的看起来需要这种神奇酱配置才能使其工作,而不像你的JSON序列化器/反序列化器那样,它只是可用的。 - JasonD
@JasonD 是的,我不喜欢没有充分理由就进行“非我即敌”(NIH),而且我也不喜欢使用XML。微软的XML DCS对于XML来说也非常高效,所以为了它所需要的努力付出相对较少的好处。 - mythz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接