我正在尝试编写正则表达式以涵盖我的所有案例。 我必须解析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"/>
我必须捕捉&#34; p2&#34;的价值。财产,我知道&#34; p2&#34;将始终排在队中。 我也希望获得&#34; p4&#34;的价值。不会永远存在的财产。
首先,我试图满足前四个案例(例子中的前四行),我写了这样的正则表达式:
\<item.+?p2=\"(?<val1>\d+)".*?(?:p4=\"(?<val2>\d+)\")?\/\>
它工作正常。 &#34; VAL1&#34;组总是返回值。并且&#34; val2&#34;如果&#34; p4&#34;组返回值财产被提出。
但要涵盖我的最后一个案例:
<item p1="1" p2="2" p3="3" p4="4" p5="5"/>
我修改了我的正则表达式:
\<item.+?p2=\"(?<val1>\d+)".*?(?:p4=\"(?<val2>\d+)\")?.*?\/\>
______________________________________________________^^^
我发现&#34; val1&#34; group仍然返回值,但&#34; val2&#34; group不再返回所有情况的值。
你能告诉我我错过了什么,并帮助写出正则表达式以涵盖我的所有案件吗?
答案 0 :(得分:0)
XML不是Regular language,因为使用正则表达式不是一种方法。您还需要parser。
有很多方法可以做到这一点,但我个人会将XML文档加载到XmlDocument类中,并使用SelectNodes方法和XPath查询来查找项目列表。完成后,您可以在每个找到的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");
}
}