2009-09-29 13 views
12

Abbiamo un campo stringa che può contenere XML o testo normale. L'XML non contiene l'intestazione <?xml e nessun elemento radice, cioè non è ben formato.Come capire se una stringa è xml?

Abbiamo bisogno di essere in grado di redigere dati XML, svuotando valori di elementi e attributi, lasciando solo il loro nome, quindi ho bisogno di verificare se questa stringa è XML prima che venga redatta.

Attualmente sto usando questo approccio:

string redact(string eventDetail) 
{ 
    string detail = eventDetail.Trim(); 
    if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail; 
    ... 

C'è un modo migliore?

Ci sono casi in cui questo approccio potrebbe mancare?

Apprezzo che potrei usare XmlDocument.LoadXml e prendere XmlException, ma questa sembra un'opzione costosa, poiché so già che molti dati non saranno in XML.

Ecco un esempio dei dati XML, oltre a mancare un elemento radice (che è stato omesso per risparmiare spazio, dal momento che ci saranno un sacco di dati), si può supporre che è ben formato:

<TableName FirstField="Foo" SecondField="Bar" /> 
<TableName FirstField="Foo" SecondField="Bar" /> 
... 

Attualmente stiamo usando solo valori basati su attributi, ma potremmo usare elementi in futuro se i dati diventano più complessi.

SOLUZIONE

Sulla base più commenti (grazie ragazzi!)

string redact(string eventDetail) 
{ 
    if (string.IsNullOrEmpty(eventDetail)) return eventDetail; //+1 for unit tests :) 
    string detail = eventDetail.Trim(); 
    if (!detail.StartsWith("<") && !detail.EndsWith(">")) return eventDetail; 
    XmlDocument xml = new XmlDocument(); 
    try 
    { 
     xml.LoadXml(string.Format("<Root>{0}</Root>", detail)); 
    } 
    catch (XmlException e) 
    { 
     log.WarnFormat("Data NOT redacted. Caught {0} loading eventDetail {1}", e.Message, eventDetail); 
     return eventDetail; 
    } 
    ... // redact 
+0

Vorrei andare con LoadXml, in questo modo si sa che i dati "XML" immessi sono validi. Se si utilizza il metodo (il codice), è possibile avere XML non valido che supererà il test. – Martin

+0

Vedere http://stackoverflow.com/questions/1072158/validate-xml-syntax-only-in-c – Graviton

+0

Scrive tu stesso? Non capisco del tutto perché tu lo stia scrivendo in un modo in cui non puoi interpretare correttamente le aree, quindi ...? –

risposta

3

Una possibilità è combinare entrambe le soluzioni. Puoi usare il tuo metodo redact e provare a caricarlo (all'interno del se). In questo modo, proverai solo a caricare ciò che è probabile che sia un xml ben formato e a scartare la maggior parte delle voci non-xml.

+0

Buona idea, grazie – si618

+0

Ho contrassegnato questa come la risposta più appropriata, perché penso che risolva il mio problema nel modo più efficiente Per la maggior parte dei casi, StartsWith filtrerà i dati non-xml e, per situazioni rare come quella descritta da Ira Baxter, l'individuazione di XmlException risolverà tutto ciò. – si618

8

Se avete intenzione di accettare non ben formato XML, in primo luogo, penso che cattura l'eccezione è il il modo migliore per gestirlo.

+0

Ti ho battuto di 2 secondi, Ha! – Martin

+0

Ah, ah! Hai vinto! – lod3n

+0

Si potrebbe anche modificare il post e mettere "Primo!" – Spence

2

Se il tuo obiettivo è l'affidabilità, l'opzione migliore è utilizzare XmlDocument.LoadXml per determinare se è XML valido o meno. Un'analisi completa dei dati può essere costosa, ma è l'unico modo per dire in modo affidabile se è XML valido o meno. Altrimenti qualsiasi carattere che non si esamina nel buffer potrebbe causare l'illegalità dei dati XML.

+0

Non penso che 'XmlDocument' sia una buona scelta qui - non ha bisogno del DOM, semplicemente per convalidare. Sembra 'XmlReader' e' try {while (reader.Read();} catch (XmlException ex) {...} 'sarebbe un approccio più leggero. –

+0

@Pavel, ma devo anche modificare l'Xml per correggere i dati, quindi la necessità di XmlDocument. – si618

+0

D'accordo, ma se combino approcci (come da idea di Samuel), allora dovrei prendere il 99% del testo in chiaro con il codice StartsWith e EndsWith e lasciare che l'altro 1% venga catturato se LoadXml lancia XmlException – si618

0

Se l'XML non contiene alcun elemento principale (vale a dire che è un frammento XML, non un documento completo), quindi il seguente sarebbe campione perfettamente valido, come pure - ma non sarebbe partita il rilevatore:

foo<bar/>baz 

Infatti, qualsiasi stringa di testo sarebbe un frammento XML valido (considera se il documento XML originale fosse solo l'elemento radice che avvolge del testo e togli i tag dell'elemento radice)!

1

Dipende dalla precisione del test che si desidera. Considerando che non hai già il file ufficiale <, stai già provando a rilevare qualcosa che non sia XML. Idealmente dovresti analizzare il testo con un parser XML completo (come suggerisci con LoadXML); tutto ciò che rifiuta non è XML. La domanda è: ti importa se accetti una stringa non XML? Per esempio, Stai bene con l'accettazione

<the quick brown fox jumped over the lazy dog's back> 

come XML e spogliandola? Se è così, la tua tecnica va bene. In caso contrario, devi decidere quanto è difficile un test e codificare un riconoscimento con quel grado di tenuta.

+0

Sì, questo è il genere di cose che ho paura di colpire – si618

1

Come vengono ricevuti i dati? Qual è l'altro tipo di dati che lo circonda? Forse c'è un modo migliore; forse puoi mettere in risalto i dati che controlli, e poi dedurre che tutto ciò che non è all'interno di quei token è XML, ma avremmo bisogno di saperne di più.

In mancanza di una soluzione carina come quella, penso che quello che hai va bene (per convalidare che inizia e finisce con quei caratteri).

Abbiamo bisogno di saperne di più sul formato dei dati in realtà.

0
try 
{ 
    XmlDocument myDoc = new XmlDocument(); 
    myDoc.LoadXml(myString); 
} 
catch(XmlException ex) 
{ 
    //take care of the exception 
} 
+1

Ovviamente, e questo è indicato nella domanda. Ma notare le eccezioni è costoso quando so che molti dati non sono xml. – si618

Problemi correlati