XmlSerializer 在遇到 xml 属性(命名空间)时崩溃

XmlSerializer crashes when encountering xml attribute (namespace)

提问人:merger 提问时间:11/3/2023 最后编辑:merger 更新时间:11/3/2023 访问量:59

问:

我正在尝试反序列化从服务获取的 XML。 但是,当遇到第一个属性时,XmlSerializer 会失败。

我缩短的 xml 如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:basicInformation xmlns:ns2="http://fu.bar.com/">
   <somenode>...</somenode>
   ...
</ns2:basicInformation>

我的班级看起来像这样

[XmlRoot(ElementName = "basicInformation")]
public class BasicInformation
{
  [XmlElement(ElementName = "somenode")]
  public string SomeNode { get; set; }

  ...

  [XmlAttribute(AttributeName = "ns2")]
  public string Ns2 { get; set; }

  [XmlText]
  public string Text { get; set; }
}

我得到的错误是这样的:

"There is an error in XML document (1, 57)."}
Data: {System.Collections.ListDictionaryInternal}
HResult: -2146233079
HelpLink: null
InnerException: {"<basicInformation xmlns='http://message.async.dms.svap.deere.com/'> was not expected."}
Message: "There is an error in XML document (1, 57)."
Source: "System.Xml"
StackTrace: "   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)\r\n   at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)\r\n   at AzureQueue.Program.Blurg() in E:\\_Code_\\Testing\\AzureQueue\\AzureQueue\\Program.cs:line 432\r\n   at AzureQueue.Program.<DoSomething>d__1.MoveNext() in E:\\_Code_\\Testing\\AzureQueue\\AzureQueue\\Program.cs:line 71"
TargetSite: {System.Object Deserialize(System.Xml.XmlReader, System.String, System.Xml.Serialization.XmlDeserializationEvents)}

如果我替换 xaml 中的第二行:

<ns2:basicInformation xmlns:ns2="http://fu.bar.com/">

对此:

<basicInformation>

一切都很好。

所以这是具有该属性的东西,我没有正确处理,但我无法找到解决方案。

我应该提到 C# 类是从 xml 到 c# 工具生成的,因为完整的 xml 很大。

那么我错过了什么?我可以用非常丑陋的方式解决这个问题并进行字符串替换,但这感觉非常错误!;)

更新

我已经接受了 Gravell @Marc回答,它有效。 但我选择使用 @Denis Micheal 解决方案,因为它解决了我的问题,而无需将命名空间放在我的 c# 模型中的所有 XML 节点上

C# XML 序列化

评论

1赞 choroba 11/3/2023
xmlns:不引入属性,而是引入命名空间声明。
0赞 Charlieface 11/3/2023
这回答了你的问题吗?XML 序列化和命名空间前缀
0赞 Nathan White 11/3/2023
如果要隐藏命名空间 URL,则已将其包含在错误代码中。

答:

2赞 Marc Gravell 11/3/2023 #1
[XmlRoot(ElementName = "basicInformation", Namespace = "http://fu.bar.com/")]
public class BasicInformation

您的数据是命名空间限定的,这很重要。您可能还需要将其单独应用于子元素,但是:请顺其自然。

评论

0赞 merger 11/3/2023
我试过这个。现在反序列化没有抛出错误。但是,返回的结果 BasicInformation 对象包含所有 null 值。
1赞 Marc Gravell 11/3/2023
@merger,那么子元素需要正确指定其命名空间 - 我怀疑在这种情况下(明确)""
0赞 Marc Gravell 11/3/2023
命名空间很困难
0赞 merger 11/3/2023
你是对的!当我修改我的 C# 类以包含空命名空间时 - [XmlElement(ElementName = “somenode”,Namespace =“”)]- 它正确反序列化了!
1赞 Denis Micheal 11/3/2023 #2

就像 @Marc Gravell 指出的那样,你的 xml 数据有一个命名空间,你在反序列化时也需要考虑这个命名空间。如果要忽略数据自带的命名空间,可以创建一个自定义的 xml 读取器来忽略命名空间

 public class IgnoreNamespaceXmlTextReader : XmlTextReader
 {
     public IgnoreNamespaceXmlTextReader(System.IO.TextReader reader) : base(reader) { }

     public override string NamespaceURI
     {
         get { return ""; }
     }
 }

然后在反序列化时


 var serializer = new XmlSerializer(typeof(BasicInformation));
 using (var stringReader = new StringReader(xml))
 {
     
     // Deserialize the XML string into a BasicInformation object
      var basicInfo = (BasicInformation)serializer.Deserialize(new IgnoreNamespaceXmlTextReader(stringReader));
 }

评论

0赞 merger 11/3/2023
这真的很有效。我将用它做更多的测试!泰
0赞 Marc Gravell 11/5/2023
几乎总是最好简单地告诉它预期的命名空间,而不是完全禁用命名空间
0赞 Denis Micheal 11/5/2023
@Marc Gravell 当然,但是由于来自外部源的 xml 数据中的可变命名空间,反序列化 xml 是一场持续的噩梦。命名空间甚至与应用程序逻辑或服务使用的数据无关。