webForumDet fria alternativet

XMLSerializer, ändra elementnamnet på obejkt i samling

.NET

12 svar · 400 visningar · startad av Compusa

Medlem sedan jan. 20023 327 inlägg
Frågan#1

Jag har ett Collection-objekt som innehåller flera SpecialItem-objekt:

[Serializable]
public class SpecialItem
{
    private int id;

    [XmlElement("specialId")]
    public int Id
    {
        get { return id; }
        set { id = value; }
    }

    ....
}

När jag serialiserar mitt Collection-objekt så får jag ett resultat i stil med:

<?xml version="1.0" ?> 
....
<specialItem>
    <specialId>1</specialId> 
</specialItem>
...

Vad jag vill kunna göra är att ändra elementnamnet specialItem i XML-filen till något annat utan att behöva ändra namn på klassen. Det fungerar ju utmärkt på properties med [XmlElement("blahablaha")], men inte på klassen... Hur göra?

Medlem sedan mars 20007 896 inlägg
#2

Vild chansning:

[XmlRoot("specialItem")]
Medlem sedan jan. 20023 327 inlägg
#3

Har redan testat det och tyvärr ger det inget resultat... Funderar på om dessa rader kanske skriver över det?

FileStream fStream = new FileStream("SpecialItems.xml", FileMode.Create, 
FileAccess.Write, FileShare.None);
XmlSerializer xmlFormat = new XmlSerializer(typeof(Collection<SpecialItem>),
    new Type[] { typeof(SpecialItem) });
xmlFormat.Serialize(fStream, specialItems);
fStream.Close();
Medlem sedan jan. 20023 327 inlägg
#4

Jag testade att bara serialisera ett objekt och inte hela min samling och då fungerar det alldeles utmärkt. men det hjälper ju inte eftersom det är hela min samling som jag ska serialisera ;)

Medlem sedan mars 20007 896 inlägg
#5

Hm.

[XmlRoot(Namespace = "http://server/NSURI", 
     ElementName = "specialItem", 
     DataType = "string", 
     IsNullable=true)]

Alt. kanske:

[XmlRootAttribute("specialItem", Namespace="http://server/NSURI", IsNullable = true)]
Medlem sedan jan. 20023 327 inlägg
#6

Har testat båda dock utan resultat. :(

Namespacet syns i xml-filen men roten blir den samma, dvs oförändrad. Verkar som att taggen för rotnamnet skrivs över när jag serialiserar min samling. Har kollat lite på AttributeOverrides som kanske kan lösa det hela...

http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlattributeoverrides.aspx

Medlem sedan jan. 20023 327 inlägg
#7

Hmm nu har jag även försökt med AttributeOverrrides utan resultat. Den som kommer på en lösning av problemet, utan att byta namn på klassen, är värd en guldstjärna :)

Medlem sedan mars 20007 896 inlägg
#8

Nu ska vi se här. Anledningen är nog så pass enkel att du inte får något rot-element när du serialiserar en hel samling av objekt. Jag gissar på att din XML-fil ser ut så här:

...
<specialItem>
  ...
</specialItem>
<specialItem>
  ...
</specialItem>
...

:q

Eftersom att ett XML-dokument inte kan innehålla rotelementet flera gånger. Det känns spontant som att du först får kapsla in din kollektion i en egen klass som ärver från Collection, istället för att använda generics. Troligtvis omständigt. ;)

Medlem sedan jan. 20023 327 inlägg
#9

Nja, jag var nog lite otydligt. Med tanke på att jag serialiserar mitt samlingsobjekt som är en Collection, så blir ju detta roten. Så här ser det ut:

<?xml version="1.0" ?> 
<ArrayOfSpecialItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<specialItem>
  ...
</specialItem>
<specialItem>
  ...
</specialItem>
</ArrayOfSpecialItem>

När jag specificerar roten på mitt SpecialItem-objekt så fungerar det om jag bara serialiserar detta. Serialiserar jag däremot hela min samling av typen Collection<SpecialItem> så ingoreras rot-attributet för ett SpecialItem och blir automagiskt namnet på klassen. Det är alltså rot-elementet på ett item-objekt jag vill ändra, inte rot-elementet på XML-filen (inte just nu i alla fall).

Det känns som jag nått en dead-end, vill helst inte behöva ändra namnet på klassen vars objekt-instanser sparas i samlingen.

Medlem sedan mars 20007 896 inlägg
#10

Ah, jag förstår.
Jag hittade nu denna, http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializationcollectionfixupcallback.aspx

Annars är min enda kvarvarande idé att du blir tvungen att skapa en egen Collection-klass för SpecialItems. :l

Medlem sedan jan. 20023 327 inlägg
#11

SPiN skrev:

Ah, jag förstår.
Jag hittade nu denna, http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializationcollectionfixupcallback.aspx

Annars är min enda kvarvarande idé att du blir tvungen att skapa en egen Collection-klass för SpecialItems. :l

Tack för länken och dina svar, ska kolla på detta imorgon och se om det löser sig :)

Medlem sedan jan. 20023 327 inlägg
#12

Nope verkar inte finnas någon riktigt smidig lösning på det här problemet, vilket är synd då XmlSerializer är smidig på många sätt. Det får bli att använda XmlTextWriter istället, där jag har mer kontroll över det XML-dokument som ska genereras.

Medlem sedan jan. 20023 327 inlägg
#13

Äntligen hittade jag en lösning som jag kan leva med och det visade sig bli en mix av XmlTextWriter och XmlSerializer :e

Istället för att serializera hela min collection så skapar jag huvudet/foten av XML-dokumentet med XmlTextWriter. Jag går sedan igenom hela min samling med items med en foreach och serialiserar varje objekt, ett efter ett.

using (XmlTextWriter xmlWriter = new XmlTextWriter("C:\\test.xml", Encoding.UTF8))
{
    xmlWriter.Formatting = Formatting.Indented;

    xmlWriter.WriteStartDocument();
    xmlWriter.WriteStartElement("En sträng");
    xmlWriter.WriteStartElement("Ännu en sträng");

    XmlSerializer xmlSerializer = new XmlSerializer(typeof(SpecialItem));

    foreach (SpecialItem item in SpecialItems)
        xmlSerializer.Serialize(xmlWriter, item);

    xmlWriter.WriteEndElement();
    xmlWriter.WriteEndElement();
}

Tack SPiN för ditt engagemang (y)

423 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
284 ms — deklarationer (db)
0 ms — hämta statistik (cache)
135 ms — hämta tråd, inlägg och bilagor (db)
137 ms — ändringar (db)