使用Regex在匹配前后分割XML字符串

时间:2012-07-10 18:38:28

标签: c# regex string split

我正在尝试格式化XML文档,因此我将字符串传递给方法,例如:

"<foo><subfoo><subsubfoo>content</subsubfoo></subfoo><subfoo/></foo>"

我正试图根据找到标签来拆分它。我想将每个元素(标记或内容)拆分为唯一的字符串,例如:

"<foo>", "<subfoo>", "<subsubfoo>", "content", "</subsubfoo>", "</subfoo>", "<subfoo/>", "</foo>"

为此我使用代码:

string findTagString = "(?<=<.*?>)";
Regex findTag = new Regex(findTagString);
List<string> textList = findTag.Split(text).ToList();

上面的代码工作正常,但它没有将“content”拆分成自己的字符串,而是:

"<foo>", "<subfoo>", "<subsubfoo>", "content</subsubfoo>", "</subfoo>", "<subfoo/>", "</foo>"

有没有办法重写正则表达式来实现这一点,将不匹配分成他们自己的字符串?

或者,重新说明:在正则表达式匹配之前和之后是否可以分割字符串?

4 个答案:

答案 0 :(得分:4)

使用此正则表达式(<.*?>)|(.+?(?=<|$)) 并将匹配转换为List<string>

答案 1 :(得分:1)

XML不是常规语言(可以通过Pumping Lemma证明),因此无法使用正则表达式解析XML。

我建议你找一个好的XML库并使用它。

答案 2 :(得分:1)

您可以通过正则表达式或xpath执行此操作,具体取决于xml的复杂程度。

如果你想使用正则表达式,你可能想要做这样的事情:

public static string xml = "<foo><subfoo><subsubfoo>content</subsubfoo></subfoo><subfoo/></foo>";
public static Regex re = new Regex(@"\<([A-Za-z0-9]*)\b[^>]*\>(.*?)\</\1\>");

static string GetContentViaRegex()
{
    string content = xml;
    while (re.IsMatch(content))
    {
        Match match = re.Match(content);
        if (!match.Success)
            break;

        content = match.Groups[2].Value;
    }
    return content;
}

正则表达式基本上搜索匹配的开始/结束标记(您不希望匹配<foo>stuff here, possibly including more tags</bar>之类的内容),并继续钻取匹配的标记,直到找到最里面的内容。这个正则表达式假设任何标签都没有属性。

如果您想通过xpath执行此操作,您可以执行以下操作:

static string GetContentViaXPath()
{
    var nav = new XPathDocument(new StringReader(xml)).CreateNavigator();
    return nav.SelectSingleNode("//text()").Value;
}

它基本上抓住了它在文档中命中的第一个文本节点。 (除非您确定输入始终有效,否则您需要添加错误检查)

答案 3 :(得分:0)

由于忽略了html规范,<>没有意义。

可以通过使用此(?<=>)|(?=<)进行拆分来完成。

这会产生

<foo>
<subfoo>
<subsubfoo>
content
</subsubfoo>
</subfoo>
<subfoo/>
</foo>