简体   繁体   English

使用未定义的名称空间前缀反序列化xml

[英]Deserializing xml with namespace prefixes that are undefined

The Xml response I receive is as follows: 我收到的Xml响应如下:

<response>
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
        <name>some name</disc-name>
        <description>some description</disc-desc>
    </item>
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.someDomain.item">
            <name>some name</disc-name>
            <description>some description</disc-desc>
    </item>
    <otherValue>12.1</otherValue>
</response>

My class is decorated as such: 我的班级装饰如下:

[XmlElement("item")]
public Item[] Items{get;set;}
[XmlElement("otherValue")
public string OtherValue{get;set;}

When I attempt to deserialize the above Xml to the class described, I receive an error of "Namespace prefix 'java' is not defined". 当我尝试将上述Xml反序列化到所描述的类时,我收到错误“名称空间前缀'java'未定义”。 Adding the "namespace" attribute to the class resolves the parsing error(however, the xml is then distorted from the original). 将“namespace”属性添加到类可以解决解析错误(但是,xml会从原始位置失真)。

ie

[XmlElement(ElementName="item",Namespace="java")]

How should I be decorating a given property to match up with a new namespace? 我应该如何装饰给定的属性以匹配新的命名空间? Or, how do I correctly define the namespace? 或者,我如何正确定义命名空间?

I'm not 100% on using a stock array for my enumerable section either, but I think the namespace issue takes precident at the moment. 我也不是100%使用库存数组作为我的可枚举部分,但我认为命名空间问题目前是预先确定的。 Any insight or thoughts are greatly appreciated! 任何见解或想法都非常感谢!

UPDATE: 更新:

I think the question is better rephrased now that I've gone back and forth a bit: 我认为这个问题现在更好地改写了,我已经来回了一下:

How do you use an XmlElementAttribute(or other attribute) to have a class that can serialize into the item snippet above, including the xsi tags? 如何使用XmlElementAttribute(或其他属性)来创建可以序列化到上面的项目片段的类,包括xsi标记?

As for my particular problem, I've realized since the Xml response is out of my control, I don't need the xsi attributes to begin with. 至于我的特殊问题,我已经意识到,由于Xml响应不受我的控制,我不需要开始使用xsi属性。 To workaround the serialization issue, I'm simply doing the following(XmlElement element contains the original document above): 要解决序列化问题,我只是执行以下操作(XmlElement元素包含上面的原始文档):

foreach(XmlNode node in element)
node.Attributes.RemoveAll();

I'm only noting my personal workaround as this is not actually a solution. 我只是注意到我的个人解决方法,因为这实际上不是解决方案。

You were right the first time. 你是第一次是对的。 "java" is not a namespace. “java”不是命名空间。 It's a namespace prefix. 它是名称空间前缀。 That's an abbreviation of the namespace, for use in the XML. 这是名称空间的缩写,用于XML。 Otherwise, the actual namespace would need to be repeated wherever you currently see "java:". 否则,无论您当前看到“java:”,都需要重复实际的命名空间。

You can use List<Item> instead of Item[] . 您可以使用List<Item>而不是Item[]

Unfortunately this is valid XML, and completely conforms to the XML Standard. 不幸的是,这是有效的XML,完全符合XML标准。 It validates, it's correct and it's complete. 它验证,它是正确的,它是完整的。

The problem you're having is in the deserialization, which is not a part of the XML Standard and is related to how .NET maps declared XML types to internal CLR types. 您遇到的问题是反序列化,它不是XML标准的一部分,而是与.NET如何将XML类型声明为内部CLR类型相关。

The xsi:type is a namespace reference and is intended to allow XML documents to substitute a derived type from another namespace for the declared type in the schema. xsi:type是名称空间引用,旨在允许XML文档将另一个名称空间中的派生类型替换为模式中的声明类型。

I know from my own experience that coders tend to react in shock that this sort of thing is even legal, much less correct XML. 根据我自己的经验,我知道编码员倾向于反应,这种事情甚至是合法的,更不正确的XML。 It basically hijacks your schema. 它基本上劫持了你的架构。

You do not need even need to include the foreign namespace in order for this to be considered correct. 您甚至不需要包含外部命名空间,以使其被认为是正确的。

(see this article for more ranting on this subject: http://norman.walsh.name/2004/01/29/trainwreck ) (有关此主题的更多咆哮,请参阅此文章: http//norman.walsh.name/2004/01/29/trainwreck

Now, as to how to handle your stated problem: deserialize this mess. 现在,至于如何处理你陈述的问题:反序列化这个烂摊子。 1) process the xml text and remove the xsi-types declaration and hope there are no fields declared that extend the base type. 1)处理xml文本并删除xsi-types声明,并希望没有声明扩展基类型的字段。 2) declare a type that derives from your base type in the schema. 2)声明从模式中的基类型派生的类型。

This looks like the following: 这看起来如下:

// note this "XmlIncludeAttribute" references the derived type.
// note that in .NET they are in the same namespace, but in XML they are in different namespaces.
[System.Xml.Serialization.XmlIncludeAttribute(typeof(DerivedType))]
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://BaseNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://BaseNameSpace", IsNullable=true)]
public partial class MyBaseType : object
{
...
}

/// <remarks/>
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://DerivedNameSpace")]
[System.Xml.Serialization.XmlRootAttribute(Namespace="http://DerivedNameSpace", IsNullable=true)]
public partial class DerivedType: MyBaseType 
{
...
}

This is only a rough outline, hopefully enough to get you started. 这只是一个粗略的轮廓,希望足以让你开始。 Note that this is not an easy problem to solve progmatically because it's always possible for someone to feed you XML and it will validate but not deserialize properly. 请注意,这不是一个容易解决的问题,因为总是有人能够为您提供XML并且它将验证但不能正确地反序列化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM