3 votes

Désérialisation de xml avec des préfixes d'espaces de noms non définis

La réponse Xml que je reçois est la suivante :

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

[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 vers la classe décrite, je reçois une erreur de "Namespace prefix 'java' is not defined". 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).

c'est-à-dire

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

Comment dois-je décorer une propriété donnée pour qu'elle corresponde à un nouvel espace de noms ? Ou, comment dois-je définir correctement l'espace de noms ?

Je ne suis pas non plus à 100% sur l'utilisation d'un tableau de stock pour ma section énumérable, mais je pense que la question de l'espace de nom prend le dessus pour le moment. Toute idée ou réflexion est la bienvenue !

UPDATE :

Je pense qu'il vaut mieux reformuler la question maintenant que j'ai fait un peu le tour de la question :

Comment utiliser un XmlElementAttribute (ou un autre attribut) pour avoir une classe qui peut se sérialiser dans le snippet d'élément ci-dessus, y compris les balises xsi ?

En ce qui concerne mon problème particulier, je me suis rendu compte que puisque 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'élément XmlElement contient le document original ci-dessus) :

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

Je ne fais que noter ma solution de contournement personnelle, car il ne s'agit pas d'une solution.

1voto

John Saunders Points 118808

Vous aviez raison la première fois. "java" n'est pas un espace de nom. C'est un préfixe d'espace de nom. C'est une abréviation de l'espace de nom, à utiliser dans le XML. Sinon, l'espace de nom réel devrait être répété partout où vous voyez actuellement "java :".

Vous pouvez utiliser List<Item> au lieu de Item[] .

0voto

Oplopanax Points 1229

Malheureusement, il s'agit d'un XML valide, qui est entièrement conforme à la norme XML. Il se valide, il est correct et il est complet.

Le problème que vous rencontrez se situe au niveau de la désérialisation, qui ne fait pas partie de la norme XML et qui est liée à la manière dont .NET fait correspondre les types XML déclarés aux types CLR internes.

Le xsi:type est une référence d'espace de nom et est destiné à permettre aux documents XML de substituer un type dérivé d'un autre espace de nom au type déclaré dans le schéma.

Je sais par expérience que les codeurs ont tendance à être choqués par le fait que ce genre de chose soit même légal, et encore moins que XML soit correct. En fait, cela détourne votre schéma.

Il n'est même pas nécessaire d'inclure l'espace de noms étranger pour que cela soit considéré comme correct.

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

Maintenant, pour ce qui est de la façon de traiter votre problème : désérialiser ce désordre. 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éclarer un type qui dérive 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 
{
...
}

Il ne s'agit là que d'une ébauche, suffisante, je l'espère, pour vous permettre de démarrer. Notez qu'il ne s'agit pas d'un problème facile à résoudre de manière progressive, car il est toujours possible que quelqu'un vous fournisse du XML qui sera validé mais ne sera pas désérialisé correctement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X