2009-07-29 8 views
3

La réponse Xml je reçois est la suivante:désérialisation XML avec des préfixes d'espace de noms qui ne sont pas définis

<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> 

Ma classe est décorée comme tel:

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

Lorsque je tente de désérialiser le Xml ci-dessus pour la classe décrite, je reçois une erreur de "namespace prefix 'java' n'est pas défini". L'ajout de l'attribut "namespace" à la classe résout l'erreur d'analyse (cependant, le xml est alors déformé par rapport à l'original).

-à-dire

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

Comment dois-je être la décoration d'une propriété donnée pour correspondre avec un nouvel espace de noms? Ou, comment puis-je définir correctement l'espace de noms? Je ne suis pas à 100% sur l'utilisation d'un tableau de stock pour ma section énumérable non plus, mais je pense que le problème d'espace de noms est précaire pour le moment. Toute idée ou pensée sont grandement appréciées!

MISE À JOUR:

Je pense mieux la question est reformulée maintenant que je suis revenu en arrière un peu:

Comment utilisez-vous un XmlElementAttribute (ou tout autre attribut) d'avoir une classe qui peut sérialiser dans l'extrait d'élément ci-dessus, y compris les balises xsi? En ce qui concerne mon problème particulier, j'ai réalisé que la réponse Xml est hors de mon contrôle, je n'ai pas besoin des attributs xsi pour commencer. Pour contourner le problème de sérialisation, je fais simplement ce qui suit (élément XmlElement contient le document original ci-dessus):

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

Je ne faisant remarquer ma solution personnelle que ce n'est pas vraiment une solution.

Répondre

0

Malheureusement, ceci est un code XML valide et est entièrement conforme à la norme XML. Il valide, c'est correct et c'est complet. Le problème que vous rencontrez est dans la désérialisation, qui ne fait pas partie de la norme XML et est liée à la façon dont les mappages .NET déclarent les types XML aux types CLR internes. Le type xsi: est une référence d'espace de noms et est destiné à permettre aux documents XML de substituer un type dérivé d'un autre espace de noms pour le type déclaré dans le schéma. Je sais d'après ma propre expérience que les codeurs ont tendance à réagir en état de choc que ce genre de chose est même légal, et encore moins correct. Il détourne fondamentalement votre schéma.

Vous n'avez même pas besoin d'inclure l'espace de noms étranger pour que cela soit considéré comme correct.

(voir cet article pour plus rodomontades sur ce sujet: http://norman.walsh.name/2004/01/29/trainwreck)

Maintenant, quant à la façon de traiter votre problème déclaré: désérialiser ce gâchis. 1) traiter le texte xml et supprimer la déclaration xsi-types et espérer qu'il n'y a pas de champs déclarés qui étendent le type de base. 2) déclarez un type dérivé de votre type de base dans le schéma.

Cela ressemble à ce qui suit:

// 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 
{ 
... 
} 

Ceci est seulement une ébauche, assez nous l'espérons pour vous aider à démarrer. Notez que ce n'est pas un problème facile à résoudre de façon progmatique car il est toujours possible pour quelqu'un de vous fournir du XML et il va valider mais pas désérialiser correctement.

1

Vous aviez raison la première fois. "java" n'est pas un espace de noms. C'est un préfixe d'espace de noms. C'est une abréviation de l'espace de noms, à utiliser dans le XML. Sinon, l'espace de noms réel devra être répété partout où vous voyez actuellement "java:". Vous pouvez utiliser List<Item> au lieu de Item[].

+0

Cela a du sens pour moi, ne pas avoir "java" répertorié comme un espace de noms. Cependant, lors de la désérialisation de la réponse Xml entrante, je reçois l'erreur "Le préfixe d'espace de noms 'java' n'est pas défini". –

+0

J'ai supposé que c'était dans le reste du document que vous n'avez pas montré. Pouvez-vous publier l'intégralité du document XML? Si 'java:' n'est pas défini, il n'y a rien que vous puissiez faire - c'est juste un mauvais XML. –

+0

Plusieurs "autres valeurs" ont été ajoutées à l'exemple ci-dessus, mais oui, à part la balise de version xml de l'en-tête, c'est tout le document. Ceci est reçu comme une réponse REST, donc je n'ai pas de contrôle sur le Xml à ma façon, juste en essayant de le convertir en un objet utilisable. –

Questions connexes