Pergunta

Eu tenho que obter um editor de configuração rápido e sujo em funcionamento. O fluxo vai algo assim:

A configuração (POCOS no servidor) é serializada para XML.
O XML está bem formado neste momento. A configuração é enviada ao servidor da Web no Xelements.
No servidor da web, o XML (sim, tudo isso) é despejado em uma textarea para edição.
O usuário edita o XML diretamente na página da web e os cliques enviam.
Na resposta, recupero o texto alterado da configuração XML. Nesse ponto, todas as fugas foram revertidas pelo processo de exibi -las em uma página da web.
Eu tento carregar a string em um objeto XML (XMLELEMENT, XELEMENT, qualquer que seja). Kaboom.

O problema é que a serialização escapa de seqüências de atributos, mas isso é perdido na tradução ao longo do caminho.

Por exemplo, digamos que eu tenha um objeto que tenha um regex. Aqui está a configuração que se trata do servidor da web:

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

Então, eu coloquei isso em uma textarea, onde se parece com isso para o usuário:

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

Portanto, o usuário faz uma ligeira modificação e envia as alterações de volta. No servidor da web, a sequência de resposta parece:

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

Portanto, o usuário adicionou outra coisa do validador e agora ambos têm atributos com caracteres ilegais. Se eu tentar carregar isso em qualquer objeto XML, ele lançará uma exceção porque <& & não será válido em uma sequência de texto. Não posso não posso usar nenhum tipo de função de codificação, pois codifica toda a coisa sangrenta:

var resultado = server.httpencode (editadoConfig);

resulta em

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

Este não é XML válido. Se eu tentar carregar isso em um elemento XML de qualquer tipo, serei atingido por uma bigorna em queda. Eu não gosto de cair bigornos.

Então, a pergunta permanece ... é a única maneira de preparar essa string xml para analisar um objeto XML é usando o regex substituindo? Existe alguma maneira de "desligar as restrições" quando eu carrego? Como você contorna isso ???


Uma última resposta e, em seguida, Wiki-Unindo, pois não acho que haja uma resposta válida.

O XML que coloco na textarea é válido, escapou XML. O processo de 1) colocando -o na área de texto 2) enviando -o para o cliente 3) exibindo -o para o cliente 4) enviando o formulário em 5) enviando -o de volta ao servidor e 6) Recuperar o valor do formulário remove Todo e qualquer escape.

Deixe-me dizer isso de novo: não estou descontando nada. Apenas exibi -lo no navegador faz isso!

Coisas para refletir: Existe uma maneira de impedir que essa redução de escape aconteça em primeiro lugar? Existe uma maneira de tomar XML quase válido e "limpar" de uma maneira segura?


Esta pergunta agora tem uma recompensa. Para coletar a recompensa, você demonstra como editar XML válido em uma janela do navegador sem uma ferramenta de terceiros/código aberto que não exige que eu use Regex para escapar dos valores do atributo manualmente, que não exige que os usuários escapem de seus atributos, e isso não falha ao arda de arrasto (& amp; amp; amp; etc;)

Foi útil?

Solução

Erm ...Quão Você serializa? Geralmente, o serializador XML nunca deve produzir XML inválido.

/Editar em resposta à sua atualização: faça não Exiba XML inválido para o seu usuário para editar! Em vez disso, exiba o XML corretamente escapado na caixa de texto. Reparar XML quebrado não é divertido e, na verdade, não vejo razão para não exibir/editar o XML de forma válida e escapada.

Mais uma vez eu poderia perguntar: Como as Você exibe o XML na caixa de texto? Você parece intencionalmente desconto o XML em algum momento.

/Editar em resposta ao seu último comentário: bem, sim, obviamente, pois ele pode conter HTML. Você precisa escapar do seu XML corretamente antes de escrevê -lo em uma página HTML. Com isso, quero dizer o todo Xml. Então, é isso:

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

torna -se o seguinte:

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

Outras dicas

É claro que quando você coloca referências de entidade dentro de uma textarea, elas saem sem estimar. Textaras não são mágicas, você tem que escapar; Tudo o que você coloca neles como todos os outros elementos. Navegadores podem exibição Um '<' cru em uma textarea, mas apenas porque eles estão tentando limpar seus erros.

Portanto, se você estiver colocando XML editável em uma textarea, precisará escapar do valor do atributo uma vez para torná -lo válido XML e, em seguida, deve escapar do XML inteiro novamente para torná -lo válido HTML. A fonte final que você deseja aparecer na página seria:

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

A pergunta é baseada em um mal -entendido do modelo de conteúdo do elemento textarea - um validador teria retirado o problema imediatamente.

ETA RE Comentário: Bem, que problema permanece? Essa é a questão do lado da serialização. Tudo o que resta está analisando-o de volta e, para isso, você deve assumir que o usuário pode criar XML bem formado.

Tentar analisar XML não formado por poços, a fim de permitir que erros como ter '<' ou 'e' não-descontados em um valor de atributo é uma perda, totalmente contra como o XML deve funcionar. Se você não pode confiar em seus usuários para escrever XML bem formado, dê-lhes uma interface não xml mais fácil, como uma lista simples de recompra de seqüências de strings regexp.

Como você diz, o serializador normal deve escapar de tudo para você.

O problema, então, é o bloco de texto: você precisa lidar com qualquer coisa passada pelo Block de texto.

Você pode experimentar o httputilidade.htmlencode (), mas acho que o método mais simples é apenas envolver qualquer coisa que você passe pelo bloco de texto em uma seção CDATA.

Normalmente, é claro que eu gostaria que tudo escapasse adequadamente, em vez de confiar na CDATA "Crutch", mas também gostaria de usar as ferramentas embutidas para fazer a fuga. Para algo que é editado em seu estado "hibernado" por um usuário, acho que o CDATA pode ser o caminho a percorrer.

Veja também a pergunta anterior:
Melhor maneira de codificar dados de texto para xml


Atualizar
Com base em um comentário para outra resposta, percebi que você está mostrando aos usuários a marcação, não apenas o conteúdo. Os analisadores XML são, bem, exigentes. Eu acho que a melhor coisa que você poderia fazer neste caso é verificar se há uma boa formação antes da aceitando o XML editado.

Talvez tente corrigir automaticamente certos tipos de erros (como amperas e ruins da minha pergunta vinculada), mas obtenha o número da linha e o número da coluna do primeiro erro de validação do analisador .NET XML e use -o para mostrar aos usuários onde seu erro é até Eles te dão algo aceitável. Pontos de bônus se você também valida contra um esquema.

Você pode dar uma olhada em algo como Tinymce, que permite editar o HTML em uma caixa de texto rica. Se você não pode configurá -lo para fazer exatamente o que deseja, poderá usá -lo como inspiração.

NOTA: O Firefox (no meu teste) não descendente em áreas de texto que você descreve. Especificamente, este código:

<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>

É alertado e exibido para o usuário inalterado, Como:

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

Então, talvez uma solução (não viável?) Seja para seus usuários usarem o Firefox.


Parece que duas partes da sua pergunta foram reveladas:

1 XML que você exibe está sendo inigualável.

Por exemplo, "&lt;"Não se sabe como" <". Mas como" <"também não se sabe como" <", a informação é perdida e você não pode recuperá -las.

Uma solução é você escapar de todos os "&"Personagens, para que"&lt;" torna-se "&amp;lt;". Isso será inigualável pela textarea como"&lt;". Quando você lê de volta, será como foi em primeiro lugar. (Suponho que a textarea realmente mude a string, mas o Firefox não está se comportando como você relata, então não posso verificar isso)

Outra solução (mencionada já, eu acho) é criar/comprar/pedir emprestado uma área de texto personalizada (não é ruim se simples, mas há todas as chaves de edição, Ctrl-C, Ctrl-Shift-Left e assim por diante).

2 Você gostaria que os usuários não precisem se preocupar em escapar.

Você está em escape-hell:

Uma substituição regex funcionará principalmente ... mas como você pode detectar com segurança a citação final ("), quando o usuário pode (legitimamente, dentro dos termos que você deu) digite:

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

Olhando para ele do ponto de vista da sintaxe regex, ele também não pode dizer se a final "faz parte do regex ou o fim dela. A sintaxe regex geralmente resolve esse problema com um terminador explícito, por exemplo:

/[^"<]/

Se os usuários usavam essa sintaxe (com o Terminator) e você escreveu um analisador para ele, poderá determinar quando o Regex terminou e, portanto, que o próximo "personagem não faz parte do regex, mas parte do XML e Portanto, quais partes precisam ser escapadas. Não estou dizendo que você deveria! Estou dizendo que é teoricamente possível. Está muito longe de ser rápido e sujo.

BTW: O mesmo problema surge para texto dentro de um elemento. O seguinte é legítimo, dentro dos termos que você deu, mas tem os mesmos problemas de análise:

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

A regra básica em uma sintaxe que permite "qualquer texto" é que o delimitador devo escapar, (por exemplo, "ou <), para que o fim possa ser reconhecido. A maioria da sintaxe também escapa de várias outras coisas, por conveniência/inconveniência. (EDITAR Ele precisará escapar para o próprio personagem de fuga: para XML, é "&", que quando literal é escapado como"&amp;"Para Regex, é o estilo C/Unix"\", que quando literal é escapado como"\\").

Sintaxe do Ninho, e você está em escape.

Uma solução simples para você é dizer aos seus usuários: este é um rápido e sujo Editor de configuração, então você não está recebendo nenhum sofisticado "sem necessidade de escapar" Mamby-Pamby:

  • Liste os personagens e escapa ao lado da área de texto, por exemplo: "<" como "&lt".
  • Para XML que não valida, mostre a eles novamente.

Olhando para trás, eu vejo Bobince deu a mesma resposta básica diante de mim.

A inserção de CDATA em torno de todo o texto lhe daria outro mecanismo de fuga que (1) salvaria os usuários de escapar manualmente e (2) ativaria o texto que não era automaticamente desdobrado pela textarea a ser lido corretamente.

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

:-)

Esse personagem especial - "<" - deveria ter substituído por outros caracteres para que seu XML seja válido. Verifique este link para caracteres especiais XML:

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

Tente também codificar seu conteúdo de bloco de texto antes de enviá -lo para o Deserializer:

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

Esta é realmente minha única opção? Não é um problema suficientemente comum para ter uma solução em algum lugar da estrutura?

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

    return configuration;
}

(Editar: AMPERSED ELETEDE A SUBSTITUIÇÃO POR SUPERIDA PROBLEMAS REDOW ROURPRIPPING)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top