【问题标题】:C# regex. Nested tags. Matching spoilers and converting them to bbcodeC# 正则表达式。嵌套标签。匹配剧透并将其转换为 bbcode
【发布时间】:2012-07-18 09:52:08
【问题描述】:

我有以下 html 代码,它的嵌套级别最高为 3:

<div class="sp-wrap">
    <div class="sp-body" title="FAQ">
        Some text
        <div class="sp-wrap">
            <div class="sp-body" title="title1"> // Level 2
            Text1...
            </div>
        </div>
        <div class="sp-wrap">
            <div class="sp-body" title="title2"> // Level 2
            Text2...
            </div>
        </div>
        <div class="sp-wrap">
            <div class="sp-body" title="title3"> // Level 2
            Text3...
            <div class="sp-wrap">
                <div class="sp-body" title="title4"> // Level 3
                Text4...
                </div>
            </div>
        </div>
    </div>
</div>

我需要将 div 标签替换为 bbcode,而我的正则表达式仅适用于未嵌套的剧透:

Regex.Replace(outstring, 
              @"<div class=""sp-body"" title=""(.*?)"">(.*?)</div>", 
              "[spoiler=$1]$2[/spoiler]", 
              RegexOptions.Singleline);

【问题讨论】:

    标签: c# regex tags nested bbcode


    【解决方案1】:

    没有测试,但这个想法应该可行:

    string s1 = Regex.Replace(outstring, @"<div class=""sp-body"" title=""(.*?)"">", "[spoiler=$1]", RegexOptions.Singleline);
    string s2 = Regex.Replace(s1, @"</div>", "[/spoiler]", RegexOptions.Singleline);
    

    编辑:

    string s1 = Regex.Replace(outstring, @"<div class=""sp-wrap"">\s*<div class=""sp-body"" title=""(.*?)"">", "[spoiler=$1]", RegexOptions.Singleline);
    string s2 = Regex.Replace(s1, @"</div>\s*</div>", "[/spoiler]", RegexOptions.Singleline);
    

    应该产生类似的东西

    [spoiler=FAQ]
        Some text
        [spoiler=title1] // Level 2
            Text1...
            [/spoiler]
        [spoiler=title2] // Level 2
            Text2...
            [/spoiler]
        [spoiler=title3] // Level 2
            Text3...
            [spoiler=title4] // Level 3
                Text4...
                [/spoiler]
        [/spoiler]
    </div>
    

    如您所见,它的缩进并不完美(我猜应该可以修复),并在示例中检测到一个缺失的&lt;/div&gt;

    【讨论】:

    • 在我的 html 代码中,我不仅有带有 sp-body 类的 div,因此替换
      是个坏主意。
  • 你的意思是,除了sp-wrap?当在示例中使用这些 sp-wrap 时,很容易避免,但如果你有一大堆不同的类,这种简单的方法就行不通了。是否考虑过 HTML 解析器?
  • 没有。 Spoiler 仅由 sp-wrap 内的 2 个 div sp-body 组成。我们如何避免使用 sp-wrap 的 div?
  • 谢谢。这个正则表达式只有在我们嵌套了剧透的情况下才有效,但如果我们没有?
  • 你是说编辑后?是的。如果 sp-wrap 是可选的,您可以全部运行它们(编辑前的那些比编辑后的晚)。
  • 【解决方案2】:

    您的代码的问题是它只会替换第一次出现和下一个最接近的 /div 出现的 div

    <div>                    // replaced
        <div>                // not replaced 
        </div>               // replaced
    </div>                   // not replaced
    

    一种方法是将其加载到 XML 中,然后使用 XPATH 仅修改您感兴趣的节点。如果是 HTML,您还可以使用 HTML 解析器,然后使用 CSS 选择器。

    您可以轻松地修改开头的 div(通过匹配类),但是正则表达式无法知道哪个是相应的结尾 div。

    【讨论】:

      【解决方案3】:

      使用 Regex 方法未完全完成此任务。使用Html Agility Pack解析Html

      【讨论】:

      • 我用它来匹配,但是根据我的例子,我们如何将html标签替换为bbcode?​​span>
      【解决方案4】:

      为你的正则表达式创建一个循环:

      var rgx = new Regex(@"<div class=""sp-body"" title=""(.*?)"">(.*?)</div>");
      while (rgx.IsMatch(outstring))
      {
          outstring = rgx.Replace(outstring, "[spoiler=$1]$2[/spoiler]");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 1970-01-01
        • 1970-01-01
        • 2020-03-06
        相关资源
        最近更新 更多