我需要使用.NET正则表达式来删除标记文件的<value>
标记之间的某些值(例如复制\粘贴摘录):
<Title>Section1</Title>
<attributeArray><name>Name1</name><value>Value1</value></attributeArray>
<attributeArray><name>Name2</name><value>Value2</value></attributeArray>
<attributeArray><name>Name3</name><value>Value3</value></attributeArray>
<attributeArray><name>Name4</name><value>Value4</value></attributeArray>
<Title>Section2</Title>
<attributeArray><name>Name1</name><value>Value1</value></attributeArray>
<attributeArray><name>Name2</name><value>Value2</value></attributeArray>
<attributeArray><name>Name3</name><value>Value3</value></attributeArray>
<attributeArray><name>Name4</name><value>Value4</value></attributeArray>
</node>
实际文本包括6个部分。我遇到的问题是每个部分的所有标签名称都是相同的,我只需要从第2节中提取值(所以不包括1,3,4,5,6)。
我已经挣扎了几天,并尝试了各种条件表达式,这对我来说是新的:
(?(<node>Section2)(.*?<value>(?<Value>.*?)<\/value>.*?))
如果是第2节,则解析值键,但它只提取第一个值 - 它不会遍历标记的每个<value>
。标记通常有大约10个我需要提取的值(在上面的例子中缩写)。
这不是在代码中完成的,所以我没有使用XML解析器的自由。
我们将非常感谢任何建议 - 或者如果我能进一步澄清,请告诉我。
一个事后的想法 - 如果有一种方法可以在每个值匹配时包含标题的文本,那么我可以解析所有6个部分,但我可以稍后根据我之后的部分过滤结果也可以。
示例:
match1
group1 = Section2
group2 = Value1
match2
group1 = Section2
group2 = Value2
match3
group1 = Section2
group2 = Value3
match4
group1 = Section2
group2 = Value4
谢谢!
答案 0 :(得分:2)
这是一个选项:
(?:
<Title>Section2</Title> # Match the header
| # or
\G(?!\A) # Match where the previous match ended
)\s*
<attributeArray>
<name>(?<name>[^<]*)</name>
<value>(?<value>[^<]*)</value>
</attributeArray>
第一场比赛包括标题,以下比赛必须从前一场比赛开始 工作示例:http://regexhero.net/tester/?id=321ce843-923d-4556-9b99-dbb72175929a
请注意,如果您在值或标题之间没有提及其他元素,则上述操作将失败。您可以使用可能效率较低的模式解决这个问题,使用事实.Net正则表达式可以具有可变长度的外观:
(?<= # lookbehind - check that before the current position
<Title>Section2</Title> # we can see the wanted title,
(?:(?!<Title>).)* # followed by no more title between it and here.
)
<attributeArray>
<name>(?<name>[^<]*)</name>
<value>(?<value>[^<]*)</value>
</attributeArray>
示例:http://regexhero.net/tester/?id=743c4de6-1b8a-48a4-a69b-63f3624de594
如果您愿意,可以将标题更改为<Title>(?<title>[^<]*)</Title>
,捕获文件中的所有值,然后按所需标题进行过滤 - 它将添加到每个匹配项中。
最后,这里有一个类似的方法可以用于其他方面:它在标题Section3
之前捕获键值/值对,假设它是有序的:
<attributeArray>
<name>(?<name>[^<]*)</name>
<value>(?<value>[^<]*)</value>
</attributeArray>
(?=
(?:(?!<Title>).)*
<Title>Section3</Title>
)
示例:http://regexhero.net/tester/?id=8d8ae0e8-5f10-439f-a5a5-50d0b4e73bd2
答案 1 :(得分:1)
我建议使用CaptureCollection:
string s = @"<Title>Section1</Title>
<attributeArray><name>Name1</name><value>Value1-1</value></attributeArray>
<attributeArray><name>Name2</name><value>Value1-2</value></attributeArray>
<attributeArray><name>Name3</name><value>Value1-3</value></attributeArray>
<attributeArray><name>Name4</name><value>Value1-4</value></attributeArray>
<Title>Section2</Title>
<attributeArray><name>Name1</name><value>Value2-1</value></attributeArray>
<attributeArray><name>Name2</name><value>Value2-2</value></attributeArray>
<attributeArray><name>Name3</name><value>Value2-3</value></attributeArray>
<attributeArray><name>Name4</name><value>Value2-4</value></attributeArray>
<Title>Section3</Title>
<attributeArray><name>Name1</name><value>Value3-1</value></attributeArray>
<attributeArray><name>Name2</name><value>Value3-2</value></attributeArray>
<attributeArray><name>Name3</name><value>Value3-3</value></attributeArray>
<attributeArray><name>Name4</name><value>Value3-4</value></attributeArray>";
Regex r = new Regex(
@"<Title>(Section2)</Title>(?:\s*<attributeArray>.*?<value>(.*?)</value></attributeArray>)+");
Match m = r.Match(s);
if (m.Success)
{
string section = m.Groups[1].Value;
int i = 0;
foreach (Capture c in m.Groups[2].Captures)
{
Console.WriteLine("match{0}\ngroup1 = {1}\ngroup2 = {2}\n",
++i, section, c.Value);
}
}
m.Groups[2].Value
会返回Value2-4
,最后要在第2组中捕获。但是所有中间捕获都被保留,可以通过Captures
property进行访问。