提问人:merger 提问时间:11/3/2023 最后编辑:merger 更新时间:11/3/2023 访问量:59
XmlSerializer 在遇到 xml 属性(命名空间)时崩溃
XmlSerializer crashes when encountering xml attribute (namespace)
问:
我正在尝试反序列化从服务获取的 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 节点上
答:
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 是一场持续的噩梦。命名空间甚至与应用程序逻辑或服务使用的数据无关。
评论
xmlns:
不引入属性,而是引入命名空间声明。