2

我在反序列化带有真正定义的“未定义”命名空间前缀的 XML 时遇到问题。

我们用 C# 发布了一个内部 Web 服务,它为各种客户提供服务。新客户端的 IDE 坚持为其 XML 输出中的每个元素声明 xsi:type,并且他们无法关闭此“功能”。

他们生成的 XML 消息是这样的,其中“命名空间”是正确的命名空间。

<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 会抛出“prefix 'ns1' not defined”错误。(它是在父节点中定义的,但显然这还不够好。)我有一个类似的问题,使用 wsdl.exe 为我生成类和反序列化输入。

使用 XmlNamespaceManager 来指定前缀似乎并不正确——类似于幻数,而且我无法预测给定消费者将声明哪个前缀。有没有办法在不剥离属性的情况下处理这个问题(books.Attributes.RemoveAll)?这也感觉不是特别优雅。

我发现 books.OuterXML 不包含任何有关“ns1”的信息,除非我破解入站元素以使用该前缀 (),所以我可以看到它为什么会抱怨,但我还不明白为什么“ns1”是'不能从上面之前的定义中识别出来。

非常感谢有人可以提供的任何帮助,或者至少是教育。

编辑:如果我更改<books>为使用前缀,即<ns1:books xsi:type="ns1:booksType">. 无论我是否定义了 xmlns,这都有效。这可能与这个答案一致,但我仍然看不到如何在服务代码中声明前缀。

@Chris,当然。希望我能在“吝啬封闭源代码”和“对那些愿意提供帮助的人有用”之间取得平衡。这里的“books”是服务方法参数中接收到的 XmlNode。(不要脱离话题,但也会虚心接受建议以改进它;我还是个新手。)

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; }
}
4

1 回答 1

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属性与XmlQualifiedName字符串变量 具有相同的值(“命名空间”)id2_namespace,但条件评估为假,因为它被编码为对象身份测试而不是字符串值等价测试。不满足此条件直接导致 OP 报告异常。

据我所见,只要被反序列化的对象的 XML 在对象的根元素名称上使用一个前缀,在该元素的 xsi:type 属性上使用另一个前缀(定义为相同的命名空间),这个错误总是会导致反序列化失败.

于 2011-01-14T18:23:54.277 回答