2012-09-04 8 views
5

Mi sembra di aver trovato qualcosa di incoerente tra le varie implementazioni XML all'interno di .Net 3.5 e sto lottando per capire che è nominalmente corretto.Come deve essere gestito il carattere ' t' all'interno dei valori degli attributi XML?

La questione è in realtà abbastanza facile da riprodurre:

  1. Creare un documento XML semplice con un elemento di testo contenente '\ t' caratteri e dargli un attributo che contiene caratteri '\ t':

    var xmlDoc = new XmlDocument { PreserveWhitespace = false, }; 
    xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>"); 
    xmlDoc.Save(@"d:\TabTest.xml"); 
    

    NB: Ciò significa che XmlDocument stesso è piuttosto soddisfatto dei caratteri "\ t" in un valore attribuite.

  2. Caricare il documento utilizzando il nuovo XmlTextReader:

    var rawFile = XmlReader.Create(@"D:\TabTest.xml"); 
    var rawDoc = new XmlDocument(); 
    rawDoc.Load(rawFile); 
    
  3. Caricare il documento utilizzando XmlReader.Create:

    var rawFile2 = new XmlTextReader(@"D:\TabTest.xml"); 
    var rawDoc2 = new XmlDocument(); 
    rawDoc2.Load(rawFile2); 
    
  4. Confronta i documenti del debugger:

    (rawDoc).InnerXml "<test><text attrib=\"Tab' 'space' '\">Tab'\t'space' '</text></test>" string 
    (rawDoc2).InnerXml "<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>" string 
    

Il documento letto utilizzando il nuovo XmlTextReader era quello che mi aspettavo, sia il '\ t' nel valore del testo che il valore dell'attributo era lì come previsto. Tuttavia, se si guarda il documento letto da XmlReader.Create, si scopre che il carattere '\ t' nel valore dell'attributo sarà stato convertito in un carattere ' '.

Che .... !! :-)

Dopo un po 'di una ricerca su Google ho scoperto che potevo codificare un' \ t 'come' & # x9; ' - se ho usato questo invece di "\ t" nell'esempio XML entrambi i lettori funzionano come previsto.

Ora Altova XmlSpy e vari altri lettori XML sembrano essere perfettamente soddisfatti dei caratteri "\ t" nei valori degli attributi, la mia domanda è qual è il modo corretto di gestirli?

Devo scrivere file XML con caratteri "\ t" codificati in valori di attributo come XmlReader.Create si aspetta o gli altri strumenti XML sono corretti e i caratteri "\ t" sono validi e XmlReader.Create è rotto?

Quale modo dovrei risolvere per risolvere questo problema?

+3

Sembra che tu abbia già trovato una soluzione alternativa - utilizzando ' '. – Oded

+0

Possibile domanda correlata: [Programmazione utilizzando il carattere di tabulazione in .NET?] (Http://stackoverflow.com/questions/294939/environment-constants) –

+0

@Oded: hai ragione - Posso usare la codifica " " ma solo se riesco a trovare un modo per scrivere il file che lo supporta. XmlDocument.Save scrive i caratteri '\ t' direttamente nel file, come fa DataSet.WriteXml. La codifica XML non dovrebbe essere qualcosa di cui mi devo preoccupare manualmente, che dovrebbe essere qualcosa che le classi XML fanno per te. Sto guardando le altre opzioni di scrittore in questo momento, ma la maggior parte sembra mantenere il "\ t" che a XmlReader.Create non piace. – SteveH

risposta

1

@all: Grazie per tutte le vostre risposte e commenti.

Sembrerebbe che Justin e Michael Kay siano corretti e lo spazio bianco dovrebbe essere codificato in base alle specifiche XML del W3C e che il problema è che un numero significativo di implementazioni MS non rispetta questo requisito.

Nel mio caso, a parte le specifiche XML, tutto quello che voglio veramente è che i valori degli attributi siano mantenuti correttamente - cioè i valori salvati dovrebbero essere esattamente i valori letti.

La risposta è forzare l'uso di un XmlWriter creato utilizzando il metodo XmlWriter.Create quando si salvano i file XML in primo luogo.

Sebbene sia Dataset che XmlDocument forniscono meccanismi di salvataggio/scrittura, nessuno di essi codifica correttamente lo spazio bianco negli attributi quando viene utilizzato nella forma predefinita. Se li impongo di utilizzare un XmlWriter creato manualmente, tuttavia, la codifica corretta viene applicata e scritta nel file.

Così il file originale di salvataggio codice diventa:

var xmlDoc = new XmlDocument { PreserveWhitespace = false, }; 
xmlDoc.LoadXml("<test><text attrib=\"Tab'\t'space' '\">Tab'\t'space' '</text></test>"); 

using (var xmlWriter = XmlWriter.Create(@"d:\TabTest.Encoded.xml")) 
{ 
    xmlDoc.Save(xmlWriter); 
} 

Questo scrittore poi codifica correttamente lo spazio bianco in modo simmetrico per il lettore XmlReader.Create di leggere senza alterare i valori degli attributi.

L'altra cosa da notare qui è che questa soluzione incapsula la codifica dal mio codice interamente mentre il lettore e lo scrittore eseguono la codifica e la decodifica in modo trasparente su lettura e scrittura.

2

Probabilmente qualcosa a che fare con la normalizzazione del valore dell'attributo. Per gli attributi CDATA è necessario un parser XML per sostituire le nuove righe e le schede nei valori degli attributi in base agli spazi, a meno che non siano scritti in forma di escape come riferimenti di carattere.

1

A prima vista sembra che XmlTextReader sia non conforme alla raccomandazione W3C. Vedere la sezione the recommendation il valore di attributo normalizzazione, specificamente

Per un carattere spazio bianco (# x20, #xD, #xA, # x9), aggiungere un carattere di spazio (# x20) al valore normalizzato.

Quindi il comportamento che non ci si aspettava (vedere uno spazio anziché una scheda) è in realtà il comportamento consigliato corretto.

Non ho idea del motivo per cui XmlTextReader si comporta in questo modo (non c'è nulla nella documentazione), tuttavia sembra che tu abbia già identificato la soluzione corretta: codifica invece l'attributo come &#x9;. In questo caso la stringa normalizzata conterrà il carattere tabulatore stesso.

+0

Grazie per quel Justin. Intendi questo per significare che un'implementazione veramente conforme al W3C DOVREBBE convertire tutti i caratteri dello spazio bianco che non sono codificati in un carattere spaziale? I caratteri dello spazio bianco presumibilmente codificati dovrebbero essere ignorati ... – SteveH

+0

@SteveH Si dice che per i riferimenti di carattere (es.caratteri codificati) dovrebbe essere usato il carattere indicato, quindi i caratteri dello spazio bianco codificati verranno sostituiti con il carattere dello spazio bianco corrispondente nel valore normalizzato. – Justin

1

Check out XmlReaderSettings.ComformanceLevel. In particolare, questa descrizione:

Si noti che gli oggetti XmlReader creati dal metodo Create sono più conformi per impostazione predefinita rispetto alla classe XmlTextReader. Di seguito sono riportati i miglioramenti di conformità che non sono abilitati sul XmlTextReader, ma sono disponibili per impostazione predefinita sui lettori creati dal metodo Create

Problemi correlati