2016-07-12 21 views
-3

我想寫正則表達式來覆蓋我所有的情況。 我必須解析Xml並捕獲一些屬性。 例子:正則表達式:不是任意的非捕獲組

<item p2="2"/> 
<item p1="1" p2="2"/> 
<item p1="1" p2="2" p3="3"/> 
<item p1="1" p2="2" p3="3" p4="4"/> 
<item p1="1" p2="2" p3="3" p4="4" p5="5"/> 

我必須抓住「P2」財產的價值,我知道,「P2」將始終存在於行。 另外,我想捕獲不會總是存在的「p4」屬性的值。

起初我想,以滿足前四例(前4行的示例中)和我寫的正則表達式是這樣的:

\<item.+?p2=\"(?<val1>\d+)".*?(?:p4=\"(?<val2>\d+)\")?\/\> 

,它工作正常。 「val1」組總是返回值。如果顯示「p4」屬性,「val2」組返回值。

但要支付我的最後一種情況:

<item p1="1" p2="2" p3="3" p4="4" p5="5"/> 

我已經修改了我的正則表達式是這樣的:

\<item.+?p2=\"(?<val1>\d+)".*?(?:p4=\"(?<val2>\d+)\")?.*?\/\> 
______________________________________________________^^^ 

而且我發現,「VAL1」組仍返回值,但「值2」組不再返回所有案例的值。

你能告訴我我錯過了什麼,並幫助寫正則表達式來涵蓋我所有的情況嗎?

Example here in Regex tester

+0

我沒有downvote你,但你的時間可能會更好地投入學習使用XML解析器。正則表達式對XML解析不太好。 –

+0

在這裏使用正則表達式將是一個真正的麻煩。你能保證參數總是以相同的順序嗎?如果不是,您將不得不爲每個可能的訂單進行更改。使用XML解析器會更加理智和安全。 – Aaron

+0

我知道寫正則表達式來解析Xml不是一個好主意。而且我已經使用其他工具來實施它。但是,雖然我的第一個實現發現了這種行爲,我想知道如何通過正則表達式來實現它。如果你想我可以重寫沒有Xml的例子。 – Aleksandr

回答

0

XML不是Regular language那裏使用正則表達式是不是要走的路。您還需要一個parser

有很多方法可以做到這一點,但我個人將XML文檔加載到一個XmlDocument類,並使用SelectNodes方法與XPath查詢找到你的產品清單。一旦你有了,你可以使用foreach每個找到XmlNode並使用Attributes集合來獲取你想要的數據。

如果你必須使用正則表達式來做到這一點,你需要做的是放在最後。 ?在非捕獲組內。你所做的是給Regex權限來省略p4補丁和匹配。?代替。通過把。*?在組內部它消除了這種可能性。這可能會很慢(甚至可能受到catastrophic backtracking的影響),並且它不能處理XML的所有複雜性。這裏是一個程序,演示:

using System; 
using System.Text.RegularExpressions; 

class Program 
{ 
    static void Main() 
    { 
     var regex = new Regex(@" 
     \<item     # Capture <item 
     .+?      # Capture one or more characters as few times as possible 
     p2=      # Capture p2= 
     \""      # Capture opening quote 
     (?<val1>\d+)   # Capture one or more decimal digits and put them in val1 
     ""      # Capture closing quote 
     .*?      # Capture zero or more characters as few times as possible 
     (?:      # Begin a non capturing group 
      p4=     # Capture p4= 
      \""     # Capture opening quote 
      (?<val2>\d+)  # Capture one or more decimal digits and put them in val2 
      \""     # Capture closing quote 
      .*?     # Capture zero or more characters as few times as possible 
     )?      # Capture 0 or 1 p4s   
     />      # Capture \> 
     ", RegexOptions.IgnorePatternWhitespace); 

     Test(regex, @"<item p2=""2""/>", "2", string.Empty); 
     Test(regex, @"<item p1=""1"" p2=""2""/>", "2", string.Empty); 
     Test(regex, @"<item p1=""1"" p2=""2"" p3=""3""/>", "2", string.Empty); 
     Test(regex, @"<item p1=""1"" p2=""2"" p3=""3"" p4=""4""/>", "2", "4"); 
     Test(regex, @"<item p1=""1"" p2=""2"" p3=""3"" p4=""4"" p5=""5""/>", "2", "4"); 
    } 

    static void Test(Regex regex, string test, string p2, string p4) 
    { 
     Match m = regex.Match(test); 

     string p2Group = m.Groups["val1"].Value; 
     string p4Group = m.Groups["val2"].Value; 

     Console.WriteLine("Test: '{0}'", test); 
     Console.WriteLine("p2: '{0}' - {1}", p2Group, p2Group == p2 ? "Success" : "Fail"); 
     Console.WriteLine("p4: '{0}' - {1}", p4Group, p4Group == p4 ? "Success" : "Fail"); 
    } 
} 
+0

我知道編寫正則表達式來解析Xml並不是一個好主意,而且我已經使用其他工具來實現它,但是當我的第一個實現發現這種行爲時,我想知道如何實現如果你想我可以重寫沒有Xml的例子 – Aleksandr

+0

寫你的沒有Xml的例子,我會給你一個更好的答案 –

+0

非常感謝,這正是我想要的對不起,我甚至不能點擊「這個答案很有用」,因爲我沒有足夠的聲譽。 – Aleksandr