我在尝试解析一些OpenXML标准(docx)时遇到问题。我们使用{Contact.MailAddress}
之类的表达式,并在第二步中从数据填充此内容。但是,Word(和LibreOffice)的方式是,他们有时会像这样分割这些标签:
<w:r w:rsidRPr="00E22BCD">
<w:rPr>
<w:rFonts w:eastAsia="Times New Roman"/>
<w:lang w:val="fr-CH"/>
</w:rPr>
<w:t>{</w:t>
</w:r>
<w:proofErr w:type="spellStart"/>
<w:r w:rsidRPr="00E22BCD">
<w:rPr>
<w:rFonts w:eastAsia="Times New Roman"/>
<w:lang w:val="fr-CH"/>
</w:rPr>
<w:t>Contakt.MailAddress</w:t>
</w:r>
<w:proofErr w:type="spellEnd"/>
<w:r w:rsidRPr="00E22BCD">
<w:rPr>
<w:rFonts w:eastAsia="Times New Roman"/>
<w:lang w:val="fr-CH"/>
</w:rPr>
<w:t>}</w:t>
</w:r>
所以我做了以下正则表达式:
(?<expr>{)((?<tag><[^>]+>)|(?<expr>[\w\s.]+))+(?<expr>})
expr
组中的所有内容都是{Contact.MailAddress}
表达式的一部分,并合并在一起。 tag
组中的所有内容都会合并到标签中,以便稍后将xml固定在一起。
现在,这非常有效。但是,当我们使用{foreach}语法时,xml可能会变得非常大,然后我们就会失控。
任何人都可以想到一个正则表达式,它可以更好地捕获这个并不会导致失控吗?
编辑1:程序是用C#/ .NET编写的。对于正则表达的味道。
编辑2:我采取了另一种方法:我列出了匹配项{[^}]}
的所有匹配项,并且在那里我用任何内容替换所有标记和空格:
var matches = Regex.Matches(xml, @"{[^}]+}")
.Cast<Match>()
.OrderByDescending(x => x.Index)
.ToList();
foreach (var match in matches)
{
var replacement = Regex.Replace(match.Value, @"<[^>]+>", "");
replacement = Regex.Replace(replacement, @"\s+", "");
xml = xml.Substring(0, match.Index) + replacement + xml.Substring(match.Index + match.Length);
}
诀窍是按索引降序对匹配进行排序,以便Substring
中的数学运算正常。
答案 0 :(得分:1)
您好像要删除{
和}
之间的所有标记和空格。如果你不担心不应该匹配的其他大括号,这应该有效:
s = Regex.Replace(s,
@"(?<brace>{)\s*(?:<[^<>]+>\s*)*|\s*(?:<[^<>]+>\s*)*(?<brace>})",
@"${brace}");
为安全起见,您可能需要添加最近的实际标签(假设它们始终相同):
@"(?<brace>{)</w:t>\s*(?:<[^<>]+>\s*)*|\s*(?:<[^<>]+>\s*)*<w:t>(?<brace>})"
使用正则表达式,我得到这个结果:
<w:r w:rsidRPr="00E22BCD">
<w:rPr>
<w:rFonts w:eastAsia="Times New Roman"/>
<w:lang w:val="fr-CH"/>
</w:rPr>
<w:t>{Contakt.MailAddress}</w:t>
</w:r>
......根本没有回溯。
编辑:
事实证明,在大括号内的点之前和之后也插入了标签。我的原始解决方案并不适用于此,所以这是一个两阶段的方法,找到大括号括起来的文本,并用删除了标签和空格的相同文本替换它:
s = Regex.Replace(s,
@"{[^{}]*}",
m => Regex.Replace(m.Value, @"\s*(?:<[^<>]+>\s*)*", ""));