C#中无法反序列化XML

4

当我尝试反序列化以下XML时,遇到了一些问题:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Response xmlns=\"http://Microsoft.LobServices.Sap/2007/03/Rfc/\">
<E_ARR>
    <ITEM xmlns=\"http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/\">
        <PROPA>00100000</PROPA>
        <PROPB>0815</PROPB>
    </ITEM>
    <ITEM xmlns=\"http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/\">
        <PROPA>00100001</PROPA>
        <PROPB>0123</PROPB>
    </ITEM>
</E_ARR>
</Response>

使用以下代码行:
var reader = new StringReader(XmlShownAbove);
var serializer = new XmlSerializer(typeof(Response));
var instance = (Response)serializer.Deserialize(reader);

以下是两个相关模型:
[XmlRoot("Response", Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/")]
public class Response
{
    [XmlArray("E_ARR", Namespace="")]
    [XmlArrayItem(typeof(ITEM), ElementName = "ITEM", Namespace="http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/")]
    public ITEM[] E_ARR{ get; set; }
}

public class ITEM
{
    [XmlElement(Namespace = "")]
    public string PROPA{ get; set; }

    [XmlElement(Namespace = "")]
    public string PROPB{ get; set; }
}

不幸的是,这段代码无法正确反序列化E_ARR数组 - 它始终保持为空,并且我无法弄清楚原因。我猜这应该是很简单的问题,但我只是没能发现它 - 提前感谢!


这是有效的XML吗? - Adriano Repetti
是的,它应该是有效的。我拿到这个XML作为实现反序列化的示例。 - MrFiveT
2
@AdrianoRepetti 我认为这只是XML在此处复制和粘贴的问题。如果E_ARR被反序列化为null,那么可以合理地假设序列化程序对XML没有问题。 - Charles Mager
是的,这是一个复制粘贴的问题。替换转义引号并没有改变任何东西。 - MrFiveT
@CharlesMager 真是太对了! - Adriano Repetti
2个回答

4

您的类与XML不完全匹配。您的E_ARR元素继承其父级的默认命名空间,因此命名空间实际上是http://Microsoft.LobServices.Sap/2007/03/Rfc/。对于PROPAPROPB也是如此。只需添加正确的命名空间即可解决您的问题:

[XmlRoot("Response", Namespace="http://Microsoft.LobServices.Sap/2007/03/Rfc/")]
public class Response
{
    [XmlArray("E_ARR", Namespace = "http://Microsoft.LobServices.Sap/2007/03/Rfc/")]
    [XmlArrayItem(typeof(ITEM), ElementName = "ITEM", Namespace="http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/")]
    public ITEM[] E_ARR{ get; set; }
}

public class ITEM
{
    [XmlElement(Namespace = "http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/")]
    public string PROPA{ get; set; }

    [XmlElement(Namespace = "http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/")]
    public string PROPB{ get; set; }
}

另外,在评论中Chris指出,省略命名空间具有相同的效果 - 继承父级的命名空间;

[XmlRoot("Response", Namespace = "http://Microsoft.LobServices.Sap/2007/03/Rfc/")]
public class Response
{
    [XmlArray("E_ARR")]
    [XmlArrayItem(typeof (ITEM), ElementName = "ITEM", Namespace = "http://Microsoft.LobServices.Sap/2007/03/Types/Rfc/")]
    public ITEM[] E_ARR { get; set; }
}

public class ITEM
{
    [XmlElement]
    public string PROPA { get; set; }

    [XmlElement]
    public string PROPB { get; set; }
}

1
我正想回答类似的问题。从属性中完全删除命名空间(空值而非具有有效值的属性)也可以起作用,这可能更容易,我认为这是完全相同的事情。 - Chris
我决定使用第二个建议的解决方案,它完美地运行。非常感谢! - MrFiveT

1

你可以添加

   <system.diagnostics>
      <switches>
         <add name="XmlSerialization.Compilation" value="1" />
      </switches>
   </system.diagnostics>

将生成的XML序列化代码文件转储到临时文件夹中的应用配置文件中。有了这些文件,您可以调试整个序列化过程并逐步执行代码。
尝试手动删除所有命名空间内容后解析文件,看看是否成功?命名空间是XML处理中最棘手的部分。

2
@Chris,我认为这是对问题的有益回答,因为它可以帮助OP找到解决问题的方法。SO并不总是提供完全可行的解决方案,但这是我的个人意见。 - Scoregraphic
我认为这是一个有帮助的评论,但不是一个有帮助的答案。SO是学习新事物的好地方,但它是一个问答网站。答案应该回答所提出的问题。这只是我的个人意见。当然,可能会有关于此的元讨论,但我对这个问题没有足够强烈的感觉去搜索它们(如果你好奇,我也没有投反对票)。 - Chris

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