2016-07-12 6 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例(例の最初の4行)を満たすためにしようとしていると私はこのような正規表現を書いた:

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

をそして、それは正常に動作します。 "val1"グループは常に値を返します。また、 "val2"グループは "p4"プロパティが提示された場合に値を返します。

しかし、私の最後のケースをカバーするために:私はこのように私の正規表現を変更した

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

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

そして、私は「VAL1」グループはまだ「val2のを」の値を返しますが、ことがわかりましたグループno moreはすべてのケースの値を返します。

あなたは私が逃していることを教えてください、そして私のすべてのケースをカバーするために正規表現を書くのに役立つでしょうか?

Example here in Regex tester

+0

私はあなたにdownvoteをしませんでしたが、あなたの時間はXMLパーサーを使うことを学ぶことにもっと投資する方がよいでしょう。正規表現はXML解析にはあまり適していません。 –

+0

ここで正規表現を使用することは本当に面倒です。引数が常に同じ順序で保証されますか?そうでない場合は、それぞれの注文に対して交替を行わなければなりません。 XMLパーサを使用すると、はるかに安全で安全です。 – Aaron

+0

私はXmlを解析する正規表現を書くことは良い考えではないことを知っています。私はすでに他の楽器を使って実装しています。しかし、私の最初の実装ではこの動作が見つかりましたが、正規表現で実装する方法は不思議です。あなたが望むなら、私はXmlなしでサンプルを書き直すことができます。 – Aleksandr

答えて

0

XMLは、正規表現を使用したためにそこRegular languageない行く方法ではありません。 parserも必要です。

これを行うには多くの方法がありますが、私は個人的にXmlDocumentクラスにXMLドキュメントをロードし、クエリでSelectNodesメソッドを使用してアイテムのリストを探します。いったんそれを持っていれば、それぞれがXmlNodeになったforeachを使用し、Attributesコレクションを使用して、必要なデータを取得できます。

正規表現を使用してこれを行う必要がある場合は、最後に行う必要があります。 ?非捕獲群の内側にある。あなたがしたことは、正規表現に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

関連する問題