实际定义时,“未定义名称空间前缀”

时间:2011-01-14 15:15:35

标签: c# xml serialization namespaces prefix

我无法使用“未定义”的名称空间前缀反序列化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一致,但我仍然不知道如何在服务代码中声明前缀。

肯定是@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; }
}

1 个答案:

答案 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属性。