2012-12-19 21 views
6

Ho guardato in giro un sacco, ma non sono stati in grado di trovare un built-in metodo Netto che sfuggirà solo caratteri XML speciali: <, >, &, ' e " se non è un tag.condizionalmente sfuggire caratteri speciali XML

Per esempio, prendete il seguente testo:

Test& <b>bold</b> <i>italic</i> <<Tag index="0" /> 

mi voglio che sia convertito in:

Test&amp; <b>bold</b> <i>italic</i> &lt;<Tag index="0" /> 

Si noti che i tag non sono sfuggiti. Fondamentalmente ho bisogno di impostare questo valore su un InnerXML di un XmlElement e, di conseguenza, questi tag devono essere conservati.

Ho cercato di implementare il mio parser e di usare uno StringBuilder per ottimizzarlo il più possibile ma può diventare piuttosto sgradevole.

Conosco anche i tag che sono accettabili e che possono semplificare le cose (solo: br, b, i, u, lampeggia, flash, Tag). Inoltre, questi tag possono essere tag di chiusura di auto

(e.g. <u />) 

o container tag

(e.g. <u>...</u>) 
+2

HTML non è XML ... come 'foo bar davvero
'. Ti divertirai moltissimo se lo vuoi fare da solo. Come opzione, considera HtmlAgilityPack per analizzare l'HTML in una struttura ragionevole e inserisci tutti i nodi con attenzione in XML ... –

+0

Niente di ciò che potresti fare semplicemente gestirà correttamente 'Test Value è < 3 but > 1'. – Bobson

+0

@Bobson '<3' non è un tag di inizio valido, quindi potresti capirlo. Ma il tuo punto è ancora valido, '<' and '>' sono escapato per rimuovere l'ambiguità nell'analisi. Ci saranno casi in cui qualsiasi parser ragionevole sceglierebbe un percorso, mentre potresti averne voluto un altro. – climbage

risposta

2

NOTA: Probabilmente questo potrebbe essere ottimizzato. E 'stato solo qualcosa che ho buttato su velocemente per te. Si noti inoltre che non sto facendo alcuna convalida dei tag stessi. Sta solo cercando contenuti racchiusi tra parentesi angolari. Fallisce anche se è stata trovata una parentesi angolare all'interno del tag (ad esempio <sometag label="I put an > here">). Oltre a questo, penso che dovrebbe fare quello che stai chiedendo.

namespace ConsoleApplication1 
{ 
    using System; 
    using System.Text.RegularExpressions; 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      // This is the test string. 
      const string testString = "Test& <b>bold</b> <i>italic</i> <<Tag index=\"0\" />"; 

      // Do a regular expression search and replace. We're looking for a complete tag (which will be ignored) or 
      // a character that needs escaping. 
      string result = Regex.Replace(testString, @"(?'Tag'\<{1}[^\>\<]*[\>]{1})|(?'Ampy'\&[A-Za-z0-9]+;)|(?'Special'[\<\>\""\'\&])", (match) => 
       { 
        // If a special (escapable) character was found, replace it. 
        if (match.Groups["Special"].Success) 
        { 
         switch (match.Groups["Special"].Value) 
         { 
          case "<": 
           return "&lt;"; 
          case ">": 
           return "&gt;"; 
          case "\"": 
           return "&quot;"; 
          case "\'": 
           return "&apos;"; 
          case "&": 
           return "&amp;"; 
          default: 
           return match.Groups["Special"].Value; 
         } 
        } 

        // Otherwise, just return what was found. 
        return match.Value; 
       }); 

      // Show the result. 
      Console.WriteLine("Test String: " + testString); 
      Console.WriteLine("Result  : " + result); 
      Console.ReadKey(); 
     } 
    } 
} 
+0

Che interrompe l'HTML valido. Ad esempio, converte '&' in '& amp;'. –

+0

Bene. Aggiustato. –

+0

@NigelWhatling Molto bello, ben fatto! L'unico difetto è che i tag non supportati non vengono sfuggiti (ad esempio non è sfuggito) – Amir

2

Io personalmente non credo sia possibile, perché si sta veramente cercando di risolvere HTML malformato, e quindi non ci non ci sono regole che puoi usare per determinare cosa deve essere codificato e cosa no.

Qualsiasi modo in cui lo si guardi, qualcosa come <<Tag index="0" /> non è un codice HTML valido.

Se conosci i tag attuali potresti creare una lista bianca che potrebbe semplificare le cose, ma dovrai attaccare il tuo problema in modo più specifico, non credo che sarai in grado di risolverlo per qualsiasi scenario . In effetti, è probabile che non ci sia in realtà alcun < casuale o > in giro nel tuo testo, e questo (probabilmente) semplificherebbe enormemente il problema, ma se stai davvero provando a trovare una soluzione generica ....Ti auguro buona fortuna.

+0

Non sarebbe possibile, tranne che sta già permettendo solo un set molto piccolo di tag validi. – Bobson

1

Ecco un'espressione regolare è possibile utilizzare che corrisponderà a qualsiasi valida < o >.

(\<(?! ?/?(?:b|i|br|u|blink|flash|Tag[^>]*))|(?<! ?/?(?:b|i|br|u|blink|flash|Tag[^>]*))\>) 

Suggerisco di inserire l'espressione di tag-test valida in una variabile e quindi di costruire il resto attorno ad esso.

var validTags = "b|i|br|u|blink|flash|Tag[^>]*"; 
var startTag = @"\<(?! ?/?(?:" + validTags + "))"; 
var endTag = @"(?<! ?/?(?:" + validTags + "))/>"; 

Poi basta fare RegEx.Replace su questi.

Problemi correlati