2011-02-09 13 views
22

Generuję plik utf-8 XML przy użyciu XDocument.XDocument: zapisywanie pliku XML do pliku bez zestawienia komponentów

XDocument xml_document = new XDocument(
        new XDeclaration("1.0", "utf-8", null), 
        new XElement(ROOT_NAME,      
        new XAttribute("note", note) 
       ) 
      ); 
... 
xml_document.Save(@file_path); 

Plik jest generowany poprawnie i sprawdzany z plikiem xsd z powodzeniem.

Kiedy próbuję przesłać plik XML do usługi online, usługa mówi, że mój plik to wrong at line 1; Odkryłem, że problem jest spowodowany przez BOM na pierwszych bajtach pliku.

Czy wiesz, dlaczego BOM jest dołączany do pliku i jak mogę zapisać plik bez niego?

Jak stwierdzono w Byte order mark Wikipedia artykuł:

Choć norma Unicode pozwala BOM w UTF-8 nie wymaga ani polecić. kolejność bajtów ma znaczenie w UTF-8, a więc BOM tylko służy do identyfikacji strumienia tekstowego lub plik jako UTF-8 lub że został przekształcony z innego formatu, który ma BOM

Czy to XDocument problem czy powinienem skontaktować się z facetami dostawcy usług internetowych, aby poprosić o aktualizację parsera?

Odpowiedz

47

Użyć XmlTextWriter i przekazać, że do XDocument za save() metoda, w ten sposób można mieć większą kontrolę nad typem kodowania używany:

var doc = new XDocument(
    new XDeclaration("1.0", "utf-8", null), 
    new XElement("root", new XAttribute("note", "boogers")) 
); 
using (var writer = new XmlTextWriter(".\\boogers.xml", new UTF8Encoding(false))) 
{ 
    doc.Save(writer); 
} 

UTF8Encoding klasy konstruktor ma przeciążenia, która określa, czy nie używać BOM (Byte Order Mark) z wartością boolowską, w twoim przypadku false.

Wynik tego kodu został zweryfikowany za pomocą Notepad ++, aby sprawdzić kodowanie pliku.

+0

Kiedy otworzysz go za pomocą Notepada ++, czy wciąż jest w utf-8, nawet używając 'nowego UTF8Encoding (false)'? – systempuntoout

+0

Myślałem, że chcesz go w UTF-8, tylko bez BOM? –

+0

Tak, zgadza się. Właśnie pytałem, czy 'nowe UTF8Encoding (false)' może mieć inne implikacje. – systempuntoout

23

Po pierwsze: dostawca usług MUSI go obsłużyć, zgodnie ze specyfikacją XML, która stwierdza, że ​​zestawienie BOM może być obecne w przypadku reprezentacji UTF-8.

można wymusić, aby zapisać XML bez BOM tak:

XmlWriterSettings settings = new XmlWriterSettings(); 
settings.Encoding = new UTF8Encoding(false); // The false means, do not emit the BOM. 
using (XmlWriter w = XmlWriter.Create("my.xml", settings)) 
{ 
    doc.Save(w); 
} 

(Googled stąd: http://social.msdn.microsoft.com/Forums/en/xmlandnetfx/thread/ccc08c65-01d7-43c6-adf3-1fc70fdb026a)

+0

* BOM może być obecny w przypadku reprezentacji UTF-8 * czy możesz wskazać mi ten konkretny dokument? – systempuntoout

+1

Oto: http://www.w3.org/TR/2006/REC-xml-20060816/#charencoding Pierwszy akapit: "Wszystkie procesory XML MUSZĄ być w stanie odczytać jednostki zarówno w UTF-8, jak i UTF-16 kodowania. " Kodowanie UTF-8 umożliwia (choć nie wymaga) BOM (patrz komentarz Joe poniżej), dlatego procesory XML muszą być w stanie przetwarzać pliki UTF-8 z LM. –

+2

"Podczas gdy standard Unicode dopuszcza BOM w UTF-8, nie wymaga tego ani go nie poleca Kolejność bajtów nie ma znaczenia w UTF-8" - http://en.wikipedia.org/wiki/Byte_order_mark –

2

najbardziej dogodny sposób, aby pozbyć się znaku BOM podczas korzystania XDocument jest po prostu zapisać dokument, a następnie zrobić prosty plik odczytany jako plik, a następnie zapisać go z powrotem. Procedury pliku obetnie znak dla ciebie:

 XDocument xTasks = new XDocument(); 
     XElement xRoot = new XElement("tasklist", 
      new XAttribute("timestamp",lastUpdated), 
      new XElement("lasttask",lastTask) 
     ); 
     ... 
     xTasks.Add(xRoot); 
     xTasks.Save("tasks.xml"); 

     // read it straight in, write it straight back out. Done. 
     string[] lines = File.ReadAllLines("tasks.xml"); 
     File.WriteAllLines("tasks.xml",lines); 

(to Hoky, ale działa w trosce o celowości - przynajmniej będziesz miał dobrze uformowany plik do przesłania do operatora internetowego);)

+3

ładnie wyjaśnione dla pierwszego postu człowiek :) – Amar

+0

Nice! Użyłem tego, ponieważ nie chciałem stracić formacji. – conor