Como diabos você pode editar XML válido em uma página da Web?

votos
4

Eu tenho que ter uma rápida e suja editor de configuração instalado e funcionando. O fluxo é algo como isto:

configuração (POCOs no servidor) são serializado para XML.
O XML está bem formado neste momento. A configuração é enviada para o servidor web em XElements.
No servidor Web, o XML (Sim, tudo isso) é despejado em uma área de texto para edição.
O usuário edita o XML diretamente na página da Web e clica em Enviar.
Na resposta, eu recuperar o texto alterado da configuração XML. Neste ponto, todas as fugas foram revertidos pelo processo de exibi-los em uma página web.
I tentar carregar a string em um objeto XML (XmlElement, XElement, qualquer que seja). KABOOM.

O problema é que escapa de serialização atribuir cordas, mas isso se perde na tradução ao longo do caminho.

Por exemplo, digamos que eu tenho um objeto que tem uma regex. Aqui está a configuração como ele vem para o servidor web:

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

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

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

Assim, o usuário faz uma ligeira modificação e submete as alterações de volta. No servidor web, a cadeia de resposta parece:

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

Assim, o usuário adicionou um outro thingie validador, e agora ambos têm atributos com caracteres ilegais. Se eu tentar carregar isso em qualquer objeto XML, ele lança uma exceção porque <e & não são válidos dentro de uma cadeia de texto. EU POSSO NÃO PODE NÃO PODE NÃO PODE NÃO usar qualquer tipo de função de codificação, uma vez que codifica toda a maldita coisa:

var resultado = Server.HttpEncode (editedConfig);

resulta em

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

Este não é um XML válido. Se eu tentar carregar isso em um elemento XML de qualquer tipo I vai ser atingido por uma bigorna caindo. Eu não gosto de queda bigornas.

Assim, a pergunta permanece ... é a única maneira que eu posso obter este XML corda pronto para analisar em um objeto XML está usando substitui regex? Existe alguma maneira de desligar restrições quando eu carregar? Como você contornar este ???


Uma última resposta e, em seguida, wiki-izing isso, como eu não acho que há uma resposta válida.

O XML coloco na textarea é válido, escapou XML. O processo de 1) colocá-lo na área de texto 2) enviá-lo para o cliente 3) exibi-lo para o cliente 4) enviar o formulário está no 5) enviá-lo de volta para o servidor e 6) recuperando o valor das remove formulário TODA E QUALQUER escapa.

Deixe-me dizer isso de novo: eu não sou un-escapar nada. Apenas exibi-lo no navegador faz isso!

Coisas para meditar sobre: ​​Existe uma maneira de evitar isso un-escapar de acontecer, em primeiro lugar? Existe uma maneira de levar XML quase válido e limpa-lo de forma segura?


Esta questão tem agora uma recompensa por isso. Para coletar a recompensa, você demonstra como editar um XML válido em uma janela do navegador sem uma ferramenta fonte 3rd party / open que não requer me usar regex para escapar atribuem valores manualmente, que não exigem que os usuários para escapar de seus atributos, e que não falha quando roundtrip (& amp; amp; amp; amp; etc;)

Publicado 28/10/2008 em 19:18
fonte usuário
Em outras línguas...                            


8 respostas

votos
7

Erm ...  Como você serializar? Normalmente, o serializador XML nunca deve produzir XML inválido.

/ EDIT em resposta a sua atualização: Você não exibir XML inválido para o usuário para editar! Em vez disso, exibir o XML corretamente escapou na caixa de texto. Reparando XML quebrado não é divertido e eu realmente não vejo nenhuma razão para não exibir / editar o XML em um válido, escapou formulário.

Mais uma vez eu poderia perguntar: como você exibir o XML na caixa de texto? Você parece unescape intencionalmente o XML em algum ponto.

/ EDIT em resposta ao seu último comentário: Bem, sim, obviamente, uma vez que o pode conter HTML. Você precisa escapar de seu XML corretamente antes de escrevê-lo para fora em uma página HTML. Com isso, quero dizer a toda XML. Então, é isso:

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

torna-se o seguinte:

&lt;foo mean-attribute="&amp;&lt;"&gt;
Respondeu 28/10/2008 em 19:22
fonte usuário

votos
5

É claro que quando você colocar referências a entidades dentro de uma textarea eles saem unescaped. Textareas não são mágicos, você tem a & fuga; tudo o que você colocar neles como qualquer outro elemento. Navegadores podem exibir uma matéria '<' em uma textarea, mas só porque eles estão tentando limpar seus erros.

Então, se você está colocando XML editável em um textarea, você precisa escapar o valor do atributo uma vez para torná-lo um XML válido, e então você tem que escapar todo o XML novamente para torná-lo HTML válido. A fonte final que você quer que apareça 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>

Pergunta é baseado em um mal-entendido sobre o modelo de conteúdo do elemento textarea - um validador teria pego o problema de imediato.

ETA re comentário: Bem, o problema permanece? Essa é a questão do lado da serialização. Tudo o que resta é analisá-lo de volta, e para isso você tem que assumir o usuário pode criar XML bem formado.

Tentando analisar XML não bem formado, de modo a permitir erros como tendo '<' ou 'e' unescaped em um valor de atributo é uma perda, totalmente contra como XML é suposto para trabalhar. Se você não pode confiar em seus usuários para escrever XML bem formado, dar-lhes uma mais fácil interface não-XML, como uma simples lista separada por nova linha de cordas de expressões regulares.

Respondeu 29/10/2008 em 13:46
fonte usuário

votos
1

Inserindo CDATA ao redor todo o texto iria dar-lhe um outro mecanismo de fuga que (1) salvar os usuários de escapar manualmente, e (2) permitir que o texto que foi unescaped automaticamente pelo textarea para ser lido correctamente.

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

:-)

Respondeu 07/02/2009 em 03:20
fonte usuário

votos
1

Nota: Firefox (no meu teste) não unescape em áreas de texto como 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 exibida para o usuário inalterada , como:

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

Então, talvez uma única solução (un-viável?) É para os seus usuários a usar firefox.


Parece duas partes para a sua pergunta foram revelados:

1 XML que você exibir está ficando unescaped.

Por exemplo, " &lt;" é unescaped como "<". Mas desde que "<" também é unescaped como "<", a informação é perdida e você não pode obtê-lo de volta.

Uma solução é para você escapar todos os " &" caracteres, de modo que " &lt;" se torna " &amp;lt;". Este, então, não ter escape pela textarea como " &lt;". Quando você lê-lo de volta, ele vai ser como era, em primeiro lugar. (Estou assumindo que o textarea realmente muda a corda, mas o Firefox não está se comportando como você denunciar, por isso não posso verificar isso)

Outra solução (já mencionado eu acho) é construir / comprar / pedir uma área de texto personalizado (não é ruim se simples, mas há todas as teclas de edição, ctrl-C, ctrl-shift esquerda e assim por diante).

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

Você está em fuga inferno:

A regex substituir a maioria irá trabalhar ... 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 o final "faz parte da regex, ou o final da mesma sintaxe Regex geralmente resolve esse problema com um terminador explícita por exemplo.:

/[^"<]/

Se os usuários utilizado esta sintaxe (com o terminador), e você escreveu um analisador para isso, então você pode determinar quando a regex terminou, e, portanto, que o próximo caractere "não é parte da regex, mas parte do XML, e portanto, que as peças precisam ser escapado. Eu não estou dizendo que você deve isso! Eu estou dizendo que é teoricamente possível. é muito longe de ser rápido e sujo.

BTW: O mesmo problema se coloca para o texto dentro de um elemento. O seguinte é legítima, nos 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 que "qualquer texto" é que o delimitador deve ser escapado, (por exemplo, "ou <), de modo que o fim pode ser reconhecido. A maioria sintaxe também escapa um monte de outras coisas, para a conveniência / inconveniente. ( EDIT ele vai precisar de ter um escape para o próprio caractere de escape: para XML, é " &", que quando literal escapou, como " &amp;" para regex, é o C / unix-style " \", que quando literal escapou como " \\").

sintaxes ninho, e você está em fuga-inferno.

Uma solução simples para você é para contar aos seus usuários: esta é uma rápida e suja editor de configuração, de modo que você não está recebendo qualquer fantasia "não há 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 irá validar, mostrar-lhes a lista novamente.

Olhando para trás, vejo bobince deu a mesma resposta básica antes de mim.

Respondeu 29/01/2009 em 19:46
fonte usuário

votos
1

Você poderia dar uma olhada em algo como TinyMCE , que permite que você edite html em uma caixa de texto rico. Se você não pode configurá-lo para fazer exatamente o que você quiser, você pode usá-lo como inspiração.

Respondeu 28/01/2009 em 03:55
fonte usuário

votos
1

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

O problema, então, é o bloco de texto: você precisa lidar com qualquer coisa passou pela textblock si mesmo.

Você pode tentar HttpUtility.HtmlEncode (), mas acho que o método mais simples é apenas para encerrar qualquer coisa que você passar pelo bloco de texto em uma seção CDATA.

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

Veja também esta pergunta anterior:
Melhor maneira de codificar os dados de texto para XML


Atualização
Baseado em um comentário para outra resposta, eu percebi que você está mostrando os usuários a marcação, não apenas o conteúdo. Analisadores XML são, bem, exigente. Acho que a melhor coisa que poderia fazer neste caso é para verificar se há boa formação antes de aceitar o XML editado.

Talvez tentar corrigir automaticamente certos tipos de erros (como maus ampersands de minha pergunta ligada), mas, em seguida, obter o número da linha e coluna número do primeiro erro de validação do analisador xml .Net e usar isso para mostrar aos usuários que o seu erro é até eles dão-lhe algo aceitável. Os pontos de bónus se você também validar contra um esquema.

Respondeu 28/10/2008 em 19:42
fonte usuário

votos
0

Isso é realmente a minha única opção? Não é este um problema bastante comum que tem uma solução em algum lugar no quadro?

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

    return configuration;
}

(Edit: excluídos de substituição e comercial, uma vez que causa problemas roundtrip)

Respondeu 28/10/2008 em 20:41
fonte usuário

votos
0

Este carácter especial - "<" - deveria ter substituído com outros personagens para que seu XML será válido. Confira neste link para XML caracteres especiais:

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

Tentar também para codificar o seu conteúdo TextBlock antes de enviá-lo para o desserializador:

HttpServerUtility utility = new HttpServerUtility();
string encodedText = utility.HtmlEncode(text);
Respondeu 28/10/2008 em 19:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more