2010-01-21 8 views
23

Ho un file XML begining in questo modo:parsing stringa XML a un documento XML ha esito negativo se la stringa inizia con <?xml... ?> sezione

<?xml version="1.0" encoding="utf-8"?> 
<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition"> 
    <DataSources> 

quando corro seguente codice:

byte[] fileContent = //gets bytes 
      string stringContent = Encoding.UTF8.GetString(fileContent); 
      XDocument xml = XDocument.Parse(stringContent); 

ottengo seguente XmlException:

I dati al livello root non sono validi. Riga 1, posizione 1.

Tagliare la versione e il nodo di codifica risolve il problema. Perché? Come elaborare questo xml correttamente?

risposta

16

Se avete solo byte si potrebbe o caricare i byte in un flusso :

XmlDocument oXML; 

using (MemoryStream oStream = new MemoryStream(oBytes)) 
{ 
    oXML = new XmlDocument(); 
    oXML.Load(oStream); 
} 

Oppure si potrebbe convertire i byte in una stringa (presumendo che si conosce la codifica) essere ribalta caricare il XML:

string sXml; 
XmlDocument oXml; 

sXml = Encoding.UTF8.GetString(oBytes); 
oXml = new XmlDocument(); 
oXml.LoadXml(sXml); 

ho mostrato il mio esempio come .NET 2.0 compatibile, se si sta utilizzando .NET 3.5 è possibile utilizzare al posto di XDocumentXmlDocument.

Caricare i byte in un flusso:

XDocument oXML; 

using (MemoryStream oStream = new MemoryStream(oBytes)) 
using (XmlTextReader oReader = new XmlTextReader(oStream)) 
{ 
    oXML = XDocument.Load(oReader); 
} 

convertire i byte in una stringa:

string sXml; 
XDocument oXml; 

sXml = Encoding.UTF8.GetString(oBytes); 
oXml = XDocument.Parse(sXml); 
+0

il problema è che ho bisogno di usare XDocument – agnieszka

+0

@agnieszka - Ho aggiornato la mia risposta per spiegarti come usare XDocument. – stevehipwell

+0

ho finito per farlo in effetti;) grazie comunque – agnieszka

6

Avete una byte-order-mark (BOM) all'inizio del vostro XML e corrisponde alla vostra codifica? Se tagli la tua intestazione, taglierai anche il BOM e se ciò non è corretto, l'analisi successiva potrebbe funzionare.

Potrebbe essere necessario ispezionare il documento a livello di byte per visualizzare la BOM.

+0

quello che è un ordine-mark di byte. ..? e come posso scoprire la codifica del documento? Sospetto solo che sia utf-8 (leggi il testo è leggibile) – agnieszka

+0

Vedi il link che ho postato. È una sequenza di byte * prima * l'intestazione che funge da direttiva per la codifica del documento. –

9

Perché preoccuparsi di leggere il file come sequenza di byte e quindi convertirlo in stringa mentre si tratta di un file xml? Basta lasciare il quadro fare il carico per voi e per far fronte alle codifiche:

var xml = XDocument.Load("test.xml"); 
+1

Perché non ottengo l'xml da un percorso. Ho appena il contenuto in byte – agnieszka

+0

E da dove vengono questi byte? Database, flusso di rete, ...? –

+0

Elenco su un punto di condivisione. Si chiama item.File.OpenBinary() – agnieszka

17

Il mio primo pensiero è stato che la codifica Unicode durante l'analisi XML da un tipo stringa .NET. Sembra, anche se l'analisi di XDocument è piuttosto permissiva rispetto a questo.

Il problema è in realtà correlato al preambolo/byte ordine UTF8 (BOM), che è una firma a tre byte optionally present all'inizio di un flusso UTF-8. Questi tre byte sono un suggerimento per la codifica utilizzata nel flusso.

È possibile determinare il preambolo di una codifica chiamando il metodo GetPreamble su un'istanza della classe System.Text.Encoding. Per esempio:

// returns { 0xEF, 0xBB, 0xBF } 
byte[] preamble = Encoding.UTF8.GetPreamble(); 

Il preambolo dovrebbe essere gestito correttamente dal XmlTextReader, così semplicemente caricare il tuo XDocument da un XmlTextReader:

XDocument xml; 
using (var xmlStream = new MemoryStream(fileContent)) 
using (var xmlReader = new XmlTextReader(xmlStream)) 
{ 
    xml = XDocument.Load(xmlReader); 
} 
+0

Si noti che il pre-amble 'UTF-8' è un'invenzione Microsoft che non è supportata da alcuno standard Unicode, a differenza delle normali BOM UTF-16. Non dovrebbe mai essere usato per scrivere, anche se dovrai gestirlo leggendo come spesso incontrerai il fastidioso combattente in natura. – bobince

+0

@bobince - Sono d'accordo (anche se è consentito dallo standard Unicode, ma il suo uso è sconsigliato - vedi pagina 36 di http://www.unicode.org/versions/Unicode5.0.0/ch02.pdf#G19273 per ulteriori informazioni informazione). –

+0

ok ma come elaborare questo xml correttamente? – agnieszka

2

Prova questa:

int startIndex = xmlString.IndexOf('<'); 
if (startIndex > 0) 
{ 
    xmlString = xmlString.Remove(0, startIndex); 
} 
+2

Sarebbe di grande aiuto se avessi spiegato che era necessario saltare il preambolo/BOM. – binki