XmlSerializer: sérialisation d'une propriété de classe comme un attribut d'un sous-élément
Je suis en utilisant un XmlSerializer
. Ma classe:
[Serializable]
[XmlRoot(ElementName="MyClass")]
public class MyClass
{
public string Value;
}
Je tiens à sérialiser en sorte que Value
se termine comme un attribut d'un sous-élément nommé (par exemple) "Texte".
Résultat escompté:
<MyClass>
<Text Value="3"/>
</MyClass>
Mais PAS (ce qui serait l'effet de marquage de la Valeur comme une XmlAttribute
)
<MyClass Value="3">
</MyClass>
Et PAS (ce qui serait l'effet de marquage de la Valeur comme une XmlElement
):
<MyClass>
<Value>3</Value>
</MyClass>
Comment puis-je y parvenir?
Je suis conscient que je pouvais changer le type de Value
de chaîne à l'autre serializable classe personnalisée.
Malheureusement, j'ai beaucoup de ces propriétés, donc j'aurais besoin de créer des dizaines de petites classes.
Est-il une solution plus rapide?
EDIT:
En réponse à vos commentaires:
- Non, pas tous les biens doit être sérialisé à un sous-élément nommé "Texte". Sous-élément du nom est unique et non ambiguë.
- Exemple de sortie XML:
<visibility> <site visible="yes"/> <comparator visible="no"/> <expiration days="7"/> <comment>blahblahblah</comment> <visibility>
- Classe exemple:
!
[XmlRoot(ElementName="Visibility")]
public class Visibility
{
[XPath("/site@visible")] //if only this was possible!
public string OnSite
{
get { return SiteVisible ? "yes" : "no"; }
}
[XPath("/comparator@visible")] //as above...
public string InComparator
{
get { return ComparatorVisible ? "yes" : "no"; }
}
[XmlIgnore]
public bool SiteVisible;
[XmlIgnore]
public bool ComparatorVisible;
[XPath("/expiration@days")] //as above...
public int ExpiresAfterDays;
[XmlElement("comment")] //this is easy
public string Comment;
}
J'ai une solution pour cela - mais pas si chaque propriété a besoin de sérialiser un élément nommé "Texte" - de sorte que vous aurez besoin de donner d'autres exemples, comme par Kirill de la demande. Le problème avec le fait d'avoir plus d'un "Texte", c'est qu'il serait impossible de désérialiser dans la direction inverse le processus ne serait pas en mesure de déterminer la propriété de chaque "Texte" cartes à. Pouvez-vous donner plus, de sorte que nous pouvons vous aider.
en aparté, je crois que tu voulais dire [XmlIgnore] au lieu de [NonSerialized].
Oh que c'est bon.
NonSerialized
est pour la sérialisation binaire.La fonctionnalité que vous recherchez n'existe pas. Mordre la balle et écrire une centaine de peu de classes. Il est fait en une seule fois.
OriginalL'auteur Konrad Morawski | 2012-02-06
Vous devez vous connecter pour publier un commentaire.
Sans changer le type de
Value
je pense qu'il n'est pas possible. Vous pouvez ajouter l'attributXmlElement(ElementName="Text")
surValue
mais vous permettra d'obtenir un résultat similaire à ceci:Édité:
Une autre solution peut impliquer de transformation XSLT: vous pouvez générer le xml à l'aide .Net de la sérialisation et après appliquer une transformation xml.
La trasformation de mon exemple doit être quelque chose comme ceci:
OriginalL'auteur Max Zerbini
Pour ce genre de flexibilité, pensez-vous vraiment que la mise en œuvre de
IXmlSerializable
que cela vous donne beaucoup plus de contrôle:Évidemment, il y a peu de travail manuel, mais il ne vous permettent de garder tous le code de sérialisation dans un seul endroit, plutôt que d'avoir une prolifération de petites classes.
L'exemple ci-dessus n'implémente que la sérialisation - vous devez écrire un équivalent désérialiser mise en œuvre si vous avez besoin de désérialiser à partir de xml à votre type.
J'ai été jouer avec une classe personnalisée pour les propriétés, PropertyXmlFormatter<T>. Vous devez ensuite faire de chaque propriété PropertyXmlFormatter<string> au lieu de string, etc. Il avait remplacé implicite de l'opérateur de cast et .Égale de sorte qu'il pourrait être utilisé comme le vrai type de l'attribution et de comparaisons. Le problème était, il a fini par être trop de travail pour le rendre valable.
OriginalL'auteur Rob Levine
Merci pour toutes les réponses. Il est dommage que .NET
XmlSerialization
bibliothèque ne permettent pas que (je pense que ça devrait le faire!). Je suis à la recherche d'une solution aussi générique que possible.Le meilleur que je pouvais venir avec (meilleur tenu compte du critère de maximum de genericity, tout en étant assez rapide à mettre en œuvre) est de laisser les
XmlSerializer
sérialiser ma classe la façon dont elle aime, puis il suffit de convertir la sortie, la délocalisation de certains éléments imbriqués endroits.Quelque chose comme ça:
Je pense que je serais de le combiner avec un attribut personnalisé (sorte de semblable à la
XPath
attribut que j'ai voulu existerait: voir l'exemple de code dans ma question), et envelopper cette fonctionnalité dans un sérialiseur classe de mon propre.Tout commentaires /points de vue sur cette approche?
Je peux penser à un potentiel de rendement inconvénient (réécriture/ré-XML après chaque sérialisation), mais le résultat de morceaux de XML ne sont pas censés être de grande taille, donc c'est probablement négligeable.
La question de la désérialisation ne me dérange pas à ce point (la désérialisation a déjà été mis en œuvre et est tout à fait "à la main", par XPath et quelques méthodes utiles).
OriginalL'auteur Konrad Morawski