2009-09-15 15 views
12

Używam tej metody serializować mojego obiektu:Jak kontrolować część serializacji xml przy użyciu .NET?

public static string XmlSerialize(object o) 
{ 
    var stringWriter = new StringWriter(); 
    var xmlSerializer = new XmlSerializer(o.GetType()); 
    xmlSerializer.Serialize(stringWriter, o); 
    string xml = stringWriter.ToString(); 
    stringWriter.Close(); 
    return xml; 
} 

To sprawia, XML, który zaczyna się tak:

<?xml version="1.0" encoding="utf-16"?> 
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 

Ale chcę, żeby wyglądać tak:

<?xml version = "1.0" encoding="Windows-1252" standalone="yes"?> 
<MyObject xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 

Jak więc zmienić kodowanie na Windows-1252 i ustawić standalone = yes? Dodatkowo, w jaki sposób uzyskać obiekt, aby wykluczyć wartość xmlns?

Widziałem kilka podobnych pytań, takich jak this one, ale miałem nadzieję, że może to być dla mnie prostsze, może ustawiając jakieś atrybuty?

Aktualizacja 2: Po przeanalizowaniu odpowiedzi i komentarzy Johna oraz przemyśleń na ten temat zdecydowałem się na drugą metodę. Nie sądzę, że tworzenie tego zwariowanego niestandardowego xml tylko dla trzeciej strony w jednym przypadku powinno być nazywane czymś tak ogólnym jak "XmlSerialize".

Więc stworzyłem drugą metodę, która pobiera dokument XML i najpierw usuwa jeden element namespace tak:

xElement.Attributes().Where(a => a.IsNamespaceDeclaration && a.Value == "http://www.w3.org/2001/XMLSchema").Remove(); 

wtedy, to zapisuje je do pliku XML z Jana kodu. Wreszcie zwraca że xml, po wyjściu z tego:

new XDeclaration("1.0", "Windows-1252", "yes").ToString() 

I to jest brzydkie, ale robi mi dokładnie to, czego potrzebuję do tego 3rd party zrozumieć mój XML.

+0

Naprawdę, użyj 'XmlReader.Create' i' XmlWriter.Create' zamiast 'XmlTextReader' i' XmlTextWriter'. Ponadto, musisz umieścić te rzeczy w blokach 'używając'. –

+0

W końcu poszedłem z twoim kodem. Ale zastanawiam się, tak długo jak wszystko zamykam, czy nie jest tak dobre, jak używanie klocków? – Chris

+0

Nie. Klocki 'using' zapewniają, że obiekty są usuwane, nawet jeśli występują wyjątki. –

Odpowiedz

25

Spróbuj tego:

public static string XmlSerialize(object o) 
{ 
    using (var stringWriter = new StringWriter()) 
    { 
     var settings = new XmlWriterSettings 
          { 
           Encoding = Encoding.GetEncoding(1252), 
           OmitXmlDeclaration = true 
          }; 
     using (var writer = XmlWriter.Create(stringWriter, settings)) 
     { 
      var xmlSerializer = new XmlSerializer(o.GetType()); 
      xmlSerializer.Serialize(writer, o); 
     } 
     return stringWriter.ToString(); 
    } 
} 

To nie będzie pozbyć się xsd: nazw, ale potem, dlaczego nie chcesz?


Aktualizacja: Wydaje się, że gdy używasz StringWriter, masz UTF-16, nawet jeśli używasz XmlWriter na wierzchu z zestawu kodowania. Następnym krokiem byłoby napisanie do MemoryStream. Ale to rodzi pytanie, dlaczego chcesz zwrócić ciąg znaków. Na przykład, jeśli masz zamiar po prostu odwrócić i wypisać ciąg do strumienia, powinniśmy wyprowadzić bezpośrednio do tego strumienia. To samo dotyczy TextWriter.

+0

Używam interfejsu API i określili, że obiekt xsd nie powinien tam być. Dlaczego tego nie chcą i dlaczego nie mogą tego po prostu zignorować Nie mam pojęcia. – Chris

+0

John, nie chcę pozbyć się deklaracji xml. Chcę go zatrzymać i zmienić wynik. – Chris

+2

Pozbądź się OmitXmlDeclaration = true, a powinieneś mieć deklarację z powrotem. Musisz wykopać swoich ludzi z API ** naprawdę ciężko **, jeśli dusi się deklaracja xsd. Konieczne będzie podanie xsi: type. Jeśli nie wszyscy przestrzegają standardów, wkrótce XML nie będzie standardem. –

2

Możesz użyć XmlTextWriter zamiast StringWriter. Oto fragment z mojego kodu z twoim zestawem kodowania.

XmlTextWriter textWriter = new XmlTextWriter(stream, Encoding.GetEncoding(1252)); 
textWriter.Namespaces = false; 
+3

'XmlTextWriter' nie powinien być już używany, od wersji .NET 2.0. –

0

FWIW, Mam kodowanie do pracy przy użyciu XmlWriter z XMLWriterSettings. Oto przykład:

... 
// My object type was from a class generated by xsd. 
XmlSerializer xms = new XmlSerializer(typeof(SomeType)); 
SomeType objSt; 
using(FileStream fs = new FileStream("C:\SomeFile.xml", FileMode.Open, FileAccess.Read)) 
{  
    using(XmlReader xr = XmlReader.Create(fs)) // Supposed to preserve encoding. 
    { 
    objSt = (SomeType)xms.Deserialize(xr); 
    }  
} 

... 
... // Do some stuff, change some attribute values. 
... 

XmlWriterSettings xsw= new XmlWriterSettings(); 
xsw.Indent= true; 
xsw.NewLineOnAttributes= true; 
xsw.Encoding = Encoding.GetEncoding(1252); 
using(XmlWriter xwXsw = XmlWriter.Create("C:\SomeFile_Changed.xml",xsw)) 
{  
    xms.Serialize(xwXsw, objSt); 
} 
... 
... // Finish up and get out. 
... 

Z jakiegoś powodu, udało mi się dostać to wszystko działa po prostu przy użyciu obiektu XmlSerializer i szeregowania z TextWriter, ponieważ zgodnie z MS pomoc dla XmlSerializer.Deserialize (XmlReader) " XmlReader automatycznie wykrywa i używa kodowania określonego przez dokument XML. " Potem zacząłem grać z XmlWriterSettings i zepsułem coś ....

+0

Spóźniony -1 za nie umieszczanie plików FileStream, 'XmlReader' i' XmlWriter' w blokach 'using'. –

+0

Cool - ale komentarz jawnie stwierdza "bez wyjątku" lub "używając" ". Nie wiem, dlaczego tak zrobiłem - dawno temu. Nie chciałem zranić twoich uczuć :) – GTAE86

+0

Który komentarz na myślisz? –

Powiązane problemy