2012-12-19 112 views
6

我環顧四周了很多,但一直沒能找到一個內置的.NET方法只會逃避特殊的XML字符: <>&'" 如果不是一個標籤。有條件逃避特殊的XML字符

例如,採取以下文字:

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

我希望它被轉換爲:

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

注意,標籤沒有逃脫。我基本上需要將此值設置爲InnerXMLXmlElement,結果,這些標記必須保留。

我已經考慮實現我自己的解析器並使用StringBuilder來儘可能地優化它,但它可能會變得非常討厭。我也知道那些可以簡化事物的標籤(只有:br,b,i,u,blink,flash,Tag)。此外,這些標籤可以自行閉合的標籤

(e.g. <u />) 

或容器標籤

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

HTML不是XML ...像'酒吧真的
'。如果你想自己做這件事,你會感到很開心。作爲選項,考慮HtmlAgilityPack將HTML解析爲一個合理的樹,並仔細地將所有節點插入XML ... –

+0

沒有什麼可以簡單地正確處理'測試值爲< 3 but > 1'。 – Bobson

+0

@Bobson'<3'不是一個有效的開始標籤,所以你可以弄清楚。但是你的觀點仍然存在,'<' and '>'被轉義以消除解析中的歧義。有些情況下,任何合理的解析器都會選擇一條路徑,而您可能想要另一條路徑。 – climbage

回答

2

注意:這可能可以優化。這只是我爲你快速打開的東西。另外請注意,我沒有對標籤本身進行任何驗證。它只是尋找包含在尖括號內的內容。如果在標籤內找到尖括號(例如<sometag label="I put an > here">),它也會失敗。除此之外,我認爲它應該做你所要求的。

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

這打破了有效的HTML。例如,它將'&'轉換爲'& amp;'。 –

+0

好。修復。 –

+0

@NigelWhatling非常好,做得好!唯一的缺點是不支持的標籤不會被轉義(例如未被轉義) – Amir

2

我個人不認爲這是可能的,因爲你確實試圖修復畸形的HTML,因此也沒有規則可以用來確定什麼是編碼,哪些不是。

任何你看它的方式,像<<Tag index="0" />是無效的HTML。

如果你知道實際的標籤,你可能會創建一個可以簡化事情的白名單,但是你將不得不更加具體地攻擊你的問題,我認爲你不能在任何情況下解決這個問題。

其實,機會是你還沒有真正得到任何隨機<>在文本躺在附近,這將(可能)大大簡化了問題,但如果你真的想拿出一個通用的解決方案....祝你好運。

+0

這是不可能的,除非他已經允許只有一小組有效的標籤。 – Bobson

1

這裏有一個正則表達式,你可以使用,將匹配任何無效<>

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

我建議把有效的標籤測試表達式放到一個變量中,然後在其周圍構造其餘的部分。

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

然後,只需做這些RegEx.Replace