Domanda

Devo mettere in funzione un editor di configurazione veloce e sporco.Il flusso è più o meno questo:

configurazione (POCO sul server) sono serializzati in XML.
A questo punto l'XML è ben formato.La configurazione viene inviata al server Web in XElements.
Sul server web, l'XML (Sì, TUTTO) viene scaricato in un'area di testo per la modifica.
L'utente modifica l'XML direttamente nella pagina Web e fa clic su Invia.
Nella risposta recupero il testo alterato della configurazione XML.A questo punto, TUTTI gli escape sono stati annullati dal processo di visualizzazione in una pagina web.
Tento di caricare la stringa in un oggetto XML (XmlElement, XElement, qualunque cosa).KABOOM.

Il problema è che la serializzazione sfugge alle stringhe di attributi, ma questa viene persa nella traduzione lungo il percorso.

Ad esempio, diciamo che ho un oggetto che ha una regex.Ecco la configurazione per quanto riguarda il server web:

<Configuration>
  <Validator Expression="[^&lt;]" />
</Configuration>

Quindi, l'ho inserito in un'area di testo, dove l'utente appare così:

<Configuration>
  <Validator Expression="[^<]" />
</Configuration>

Quindi l'utente apporta una leggera modifica e invia nuovamente le modifiche.Sul server web, la stringa di risposta è simile a:

<Configuration>
  <Validator Expression="[^<]" />
  <Validator Expression="[^&]" />
</Configuration>

Quindi, l'utente ha aggiunto un altro validatore e ora ENTRAMBI hanno attributi con caratteri illegali.Se provo a caricarlo in qualsiasi oggetto XML, genera un'eccezione perché < e & non sono validi all'interno di una stringa di testo.NON POSSO NON POSSO NON POSSO usare alcun tipo di funzione di codifica, poiché codifica l'intera dannata cosa:

var risultato = Server.HttpEncode(editedConfig);

risultati in

&lt;Configuration&gt;
  &lt;Validator Expression="[^&lt;]" /&gt;
  &lt;Validator Expression="[^&amp;]" /&gt;
&lt;/Configuration&gt;

Questo NON è un XML valido.Se provo a caricarlo in un elemento XML di qualsiasi tipo verrò colpito da un'incudine che cade.Non mi piacciono le incudini che cadono.

Quindi la domanda rimane...L'UNICO modo in cui posso preparare questa stringa XML per l'analisi in un oggetto XML è utilizzare le sostituzioni regex?Esiste un modo per "disattivare i vincoli" quando carico?Come aggirare questo problema???


Un'ultima risposta e poi wiki, poiché non penso che ci sia una risposta valida.

L'XML che inserisco nell'area di testo È valido, XML con escape.Il processo di 1) inserirlo nell'area di testo 2) inviarlo al client 3) visualizzarlo al client 4) inviare il modulo in cui si trova 5) inviarlo nuovamente al server e 6) recuperare il valore dal modulo RIMUOVE QUALSIASI E TUTTO FUGA.

Lasciatemelo dire ancora:Non sto scappando da NIENTE.Basta visualizzarlo nel browser per farlo!

Cose su cui riflettere:C'è un modo per evitare che questa fuga non accada in primo luogo?Esiste un modo per prendere XML quasi valido e "pulirlo" in modo sicuro?


Questa domanda ora ha una taglia su di essa.Per raccogliere la ricompensa, dimostri come modificare XML VALID in una finestra del browser SENZA uno strumento di terze parti/open source che non richieda l'uso di espressioni regolari per eseguire l'escape manuale dei valori degli attributi, che non richieda agli utenti di eseguire l'escape dei propri attributi, e questo non fallisce durante il roundtripping (&amp;amp;etc;)

È stato utile?

Soluzione

Erm & # 8230; & nbsp; Come serializzi? Di solito, il serializzatore XML non dovrebbe mai produrre XML non valido.

/ EDIT in risposta al tuo aggiornamento: non visualizza XML non valido per il tuo utente da modificare! Invece, visualizza l'XML con escape corretto nella TextBox. La riparazione di XML non funzionante non è divertente e in realtà non vedo alcun motivo per non visualizzare / modificare l'XML in un formato valido, con escape.

Ancora una volta potrei chiedere: come visualizzi l'XML nella TextBox? Ad un certo punto sembri intenzionalmente annullare l'escape dell'XML.

/ EDIT in risposta al tuo ultimo commento: Beh sì, ovviamente, dal momento che può contenere HTML. Devi uscire correttamente dal tuo XML prima di scriverlo in una pagina HTML. Con ciò, intendo il intero XML. Quindi questo:

<foo mean-attribute="&lt;">

diventa questo:

&lt;foo mean-attribute="&amp;&lt;"&gt;

Altri suggerimenti

Ovviamente quando si inseriscono riferimenti a entità all'interno di un'area di testo, questi escono senza caratteri di escape. Le textareas non sono magiche, devi & Amp; escape; tutto ciò che ci metti proprio come ogni altro elemento. I browser potrebbero visualizzare un '& Lt;' grezzo in una textarea, ma solo perché stanno cercando di ripulire i tuoi errori.

Quindi, se stai inserendo XML modificabile in un'area di testo, devi sfuggire al valore dell'attributo una volta per renderlo XML valido, quindi devi fuggire di nuovo l'intero XML per renderlo HTML valido. La fonte finale che si desidera visualizzare nella pagina sarebbe:

<textarea name="somexml">
    &lt;Configuration&gt;
        &lt;Validator Expression="[^&amp;lt;]" /&gt;
        &lt;Validator Expression="[^&amp;amp;]" /&gt;
    &lt;/Configuration&gt;
</textarea>

La domanda si basa su un'incomprensione del modello di contenuto dell'elemento textarea: un validatore avrebbe subito capito il problema.

ETA re comment: Bene, quale problema rimane? Questo è il problema sul lato della serializzazione. Tutto ciò che rimane è analizzarlo nuovamente, e per questo devi supporre che l'utente possa creare un XML ben formato.

Prova di analizzare XML non ben formato, al fine di consentire errori come avere "< ' o '& amp;' senza escape in un valore di attributo è una perdita, totalmente contro il modo in cui XML dovrebbe funzionare. Se non puoi fidarti dei tuoi utenti di scrivere XML ben formati, offri loro un'interfaccia non XML più semplice, come un semplice elenco separato da righe di regexp.

Come dici tu, il normale serializzatore dovrebbe sfuggirti a tutto.

Il problema, quindi, è il blocco di testo:devi gestire tu stesso tutto ciò che passa attraverso il blocco di testo.

Potresti provare HttpUtility.HtmlEncode(), ma penso che il metodo più semplice sia semplicemente racchiudere tutto ciò che passi attraverso il blocco di testo in una sezione CDATA.

Normalmente, ovviamente, vorrei che tutto fosse correttamente sfuggito piuttosto che fare affidamento sulla "stampella" CDATA, ma vorrei anche utilizzare gli strumenti integrati per eseguire l'escape.Per qualcosa che viene modificato nel suo stato "ibernato" da un utente, penso che CDATA potrebbe essere la strada da percorrere.

Vedi anche questa domanda precedente:
Il modo migliore per codificare dati di testo per XML


Aggiornamento
Sulla base di un commento a un'altra risposta, mi sono reso conto che stai mostrando agli utenti il ​​markup, non solo i contenuti.I parser XML sono, beh, schizzinosi.Penso che la cosa migliore che potresti fare in questo caso sia verificare la buona forma Prima accettando l'xml modificato.

Forse prova a correggere automaticamente alcuni tipi di errori (come le e commerciali errate dalla mia domanda collegata), ma poi ottieni il numero di riga e il numero di colonna del primo errore di convalida dal parser xml .Net e usalo per mostrare agli utenti dove si trova il loro errore fino a quando ti danno qualcosa di accettabile.Punti bonus se convalidi anche rispetto a uno schema.

Potresti dare un'occhiata a qualcosa come TinyMCE , che ti permette di modificare l'html in un rich text scatola. Se non riesci a configurarlo per fare esattamente quello che vuoi, puoi usarlo come ispirazione.

Nota: firefox (nel mio test) non ripristina le aree di testo come descritto. Nello specifico, questo codice:

<textarea cols="80" rows="10" id="1"></textarea>

<script>
elem = document.getElementById("1");

elem.value = '\
<Configuration>\n\
  <Validator Expression="[^&lt;]" />\n\
</Configuration>\
'
alert(elem.value);
</script>

Viene avvisato e visualizzato all'utente invariato , come:

<Configuration>
  <Validator Expression="[^&lt;]" />
</Configuration>

Quindi forse una soluzione (non praticabile?) è che i tuoi utenti possano usare Firefox.


Sembra che due parti della tua domanda siano state rivelate:

1 XML che visualizzi non viene sottoposto a escape.

Ad esempio, " &lt; " è senza caratteri di escape come " < " ;. Ma poiché & Quot; & Lt; & Quot; viene anche convertito in " < " ;, le informazioni vengono perse e non è possibile recuperarle.

Una soluzione è per te per sfuggire a tutte le " & " caratteri, in modo che " &amp;lt; " diventa " &amp; " ;. Questo verrà quindi eliminato dall'area di testo come & Quot; \ & Quot ;. Quando lo rileggi, sarà come era in primo luogo. (Suppongo che l'area di testo cambi effettivamente la stringa, ma Firefox non si comporta come riportato, quindi non posso verificarlo)

Un'altra soluzione (menzionata già credo) è quella di costruire / acquistare / prendere in prestito un'area di testo personalizzata (non male se semplice, ma ci sono tutti i tasti di modifica, ctrl-C, ctrl-shift-sinistra e così via).

2 Vorresti che gli utenti non dovessero preoccuparsi di scappare.

Sei in un inferno di fuga:

Una sostituzione regex funzionerà principalmente ... ma come si può rilevare in modo affidabile la citazione finale ("), quando l'utente potrebbe (legittimamente, entro i termini che hai indicato) inserire:

<Configuration>
  <Validator Expression="[^"<]" />
</Configuration>

Guardandolo dal punto di vista della sintassi della regex, non può nemmeno dire se la <<>> finale; fa parte del regex, o la sua fine. La sintassi Regex di solito risolve questo problema con un terminatore esplicito, ad esempio:

/[^"<]/

Se gli utenti hanno usato questa sintassi (con il terminatore) e hai scritto un parser per esso, allora potresti determinare quando è terminata la regex e quindi che la prossima " il carattere non fa parte della regex, ma parte dell'XML e quindi quali parti devono essere sfuggite. Non sto dicendo che dovresti farlo! Sto dicendo che è teoricamente possibile. È piuttosto lontano dall'essere veloce e sporco.

A proposito: lo stesso problema si presenta per il testo all'interno di un elemento. Quanto segue è legittimo, nei termini indicati, ma presenta gli stessi problemi di analisi:

<Configuration>
  <Expression></Expression></Expression>
</Configuration>

La regola di base in una sintassi che consente " qualsiasi testo " è che il delimitatore deve essere evaso, (ad esempio " o <), in modo che la fine possa essere riconosciuta. La maggior parte della sintassi sfugge anche a un sacco di altre cose, per comodità / inconveniente. ( EDIT dovrà avere una escape per il carattere di escape stesso: per XML, è " \\ " ;, che quando il valore letterale viene evitato come " &lt " Per regex, è lo stile C / unix " <=> " ;, che quando il valore letterale viene evitato come " <=> < !> quot;).

Annidate le sintassi e siete in un inferno di fuga.

Una semplice soluzione per te è quella di dire ai tuoi utenti: questo è un editor di configurazione veloce e sporco , quindi non otterrai alcuna quotazione &; non c'è bisogno di sfuggire a " Mamby-pamby:

  • Elenca i caratteri e le fughe successive nell'area di testo, ad esempio: " < " come quot &; <=> quot &;.
  • Per XML che non lo farà convalida, mostra loro di nuovo l'elenco.

Guardando indietro, vedo bobince mi ha dato la stessa risposta di base.

L'inserimento di CDATA in tutto il testo ti darebbe un altro meccanismo di escape che (1) salverebbe gli utenti dall'evasione manuale e (2) consentirebbe la rilettura corretta del testo che era stato automaticamente rimosso dall'area di testo.

 <Configuration>
   <Validator Expression="<![CDATA[  [^<]   ]]>" />
 </Configuration>

: -)

Questo carattere speciale - " < " - avrebbe dovuto essere sostituito con altri caratteri in modo che il tuo XML sia valido. Controlla questo collegamento per i caratteri speciali XML:

http://en.wikipedia.org/wiki/List_of_XML_andencesHa_ML

Prova anche a codificare il contenuto di TextBlock prima di inviarlo al deserializer:

HttpServerUtility utility = new HttpServerUtility();
string encodedText = utility.HtmlEncode(text);

Questa è davvero la mia unica opzione? Non è questo un problema abbastanza comune da avere una soluzione da qualche parte nel framework?

private string EscapeAttributes(string configuration)
{
    var lt = @"(?<=\w+\s*=\s*""[^""]*)<(?=[^""]*"")";
    configuration = Regex.Replace(configuration, lt, "&lt;");

    return configuration;
}

(modifica: sostituzione della e commerciale cancellata poiché causa problemi di arrotondamento)

scroll top