我无法使用“未定义”的名称空间前缀反序列化XML,而这种前缀确实是定义的。
我们在C#中发布了一个内部Web服务,为各种客户提供服务。新客户端的IDE坚持为其XML输出中的每个元素声明xsi:type,并且它们无法关闭此“功能”。
他们生成的XML消息是这样的,其中“namespace”是正确的命名空间。
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<myOperation xsi:type="ns1:namespace" xmlns="namespace" xmlns:ns1="namespace">
<inputString xsi:type="xsd:string">ABCDEF</inputString>
<books xsi:type="ns1:booksType">
<bookID xsi:type="xsd:string">ABC123</bookID>
<bookID xsi:type="xsd:string">DEF456</bookID>
</books>
<!-- ... snip... -->
</myOperation>
</soapenv:Body>
<books>
基本上是一个字符串数组。
服务方法接受为XmlNode,但XmlSerializer抛出“前缀'ns1'未定义”错误。 (它在父节点中定义,但显然不够好。)我有一个类似的问题,使用wsdl.exe生成类并为我反序列化输入。
使用XmlNamespaceManager指定前缀似乎不对 - 类似于魔术数字,我无法预测给定的消费者无论如何都会声明哪个前缀。有没有办法处理这个而不剥离属性(books.Attributes.RemoveAll)?这也不是特别优雅。
我发现books.OuterXML不包含'ns1'的任何信息,除非我破解元素入站使用该前缀(),所以我可以看到它为什么抱怨,但我还不明白为什么' ns1'无法从上面的定义中识别出来。
非常感谢有人提供的任何帮助,或者至少是教育。
编辑:如果我更改<books>
以使用前缀,即<ns1:books xsi:type="ns1:booksType">
,则可以正常工作。无论我是否定义了xmlns,这都有效。这可能与this answer一致,但我仍然不知道如何在服务代码中声明前缀。
XmlSerializer xmlSerializer = new XmlSerializer(typeof(booksType));
StringReader xmlDataReader = new StringReader(books.OuterXml);
books = (booksType)xmlSerializer.Deserialize(xmlDataReader);
课程就是这样:
[Serializable()]
[XmlRoot("books", Namespace = "namespace")]
[XmlTypeAttribute(TypeName = "booksType", Namespace = "namespace")]
public class booksType
{
[XmlElement(ElementName = "bookID")]
public string[] bookIDs { get; set; }
}
答案 0 :(得分:2)
您的反序列化代码可能如下所示:
XmlSerializer sz = new XmlSerializer(typeof(booksType));
var reader = new XmlNodeReader(booksXmlNode);
var books = sz.Deserialize(reader);
[编辑]这是更好的,因为命名空间声明是使用XmlNode保留的,而通过OuterXml转换为XML字符串似乎切断了ns1前缀的名称空间声明,然后序列化程序对类型属性值进行了barfs包含此前缀。我想这是XML实现中的一个错误,但也许XML大师可以证实这一点。
这可以让你超越你所看到的错误,但它是否完全解决了这个问题我不确定。
[进一步编辑]如下面的评论所述,.NET XmlSerializer中存在一个错误,导致反序列化失败。单步执行生成的程序集中的反序列化代码,可以测试以下条件:
(object) ((System.Xml.XmlQualifiedName)xsiType).Namespace == (object)id2_namespace))
虽然Namespace
的{{1}}属性与字符串变量XmlQualifiedName
具有相同的值('namespace'),但条件的计算结果为false,因为它被编码为对象身份测试而不是字符串值等价测试。如果失败,则直接导致OP报告的异常。
据我所知,只要反序列化对象的XML在对象的根元素名称上使用一个前缀,并在该元素的xsi上使用另一个前缀(定义为相同的名称空间),此错误将始终导致反序列化失败:type属性。