【问题标题】:.NET regex to replace start and end tags based on attribute with same ending tags.NET 正则表达式基于具有相同结束标签的属性替换开始和结束标签
【发布时间】:2015-07-09 10:08:51
【问题描述】:

结束标签相同时,如何根据属性替换标签?

例子:

<tag id='bold'><tag id='italic'>Hello World</tag></tag>

<b><i>Hello World</i></b>

这可以通过 RegEx 实现吗?还是我需要编写自定义解析方法?

注意:这是一个简化示例,不适用于 HTML 浏览器。

【问题讨论】:

  • 根据你的 html 的复杂程度和标签的深度,你不能用正则表达式编写一个通用的解决方案。您可以在标记中使用&lt;tag&gt;[\s\S]*?(&lt;tag&gt;[\s\S]*?&lt;/tag&gt;)*[\s\S]*?&lt;/tag&gt;... 行中的某些内容来描述可选的&lt;tag&gt;&lt;/tag&gt; 结构,然后... 内...的另一个级别的可选标记结构等等。使用其他东西。
  • 输入的是格式良好的 XML 文件吗?如果是这样,我会认真考虑使用 XSLT。
  • 试试这个简洁的正则表达式:(?s)&lt;tag\s+id='bold'(?:(?:(?!&lt;/?tag).)|(?&lt;c&gt;&lt;tag\b)|(?&lt;-c&gt;(?&lt;=(\b[^&gt;&lt;]*)?)&lt;/tag&gt;))+(?(c)(?!))&lt;/tag&gt; 并替换为 &lt;b&gt;&lt;i&gt;$1&lt;/i&gt;&lt;/b&gt; (Test) 开玩笑 :] 确定解析器解决方案在这里更好。

标签: .net regex vb.net


【解决方案1】:

这是一种使用XElementXPathLINQ 的方法:

Dim str As String = "<tag id='bold'><tag id='italic'>Hello World</tag></tag>"
Dim xDoc As XDocument = XDocument.Parse("<?xml version= '1.0'?><root>" + str + "</root>")
Dim query = xDoc.XPathSelectElements("//tag")
For Each element In query
   If element.HasAttributes = True Then
        If element.Attribute("id").Value = "italic" Then
           element.Name = "i"
        ElseIf element.Attribute("id").Value = "bold" Then
           element.Name = "b"
        End If
        element.RemoveAttributes()
    End If
Next element
str = xDoc.ToString(System.Xml.Linq.SaveOptions.DisableFormatting).Replace("<root>", String.Empty).Replace("</root>", String.Empty)

输出:

不要忘记添加这些usings:

Imports System.Xml.Linq
Imports System.Xml
Imports System.Xml.XPath

【讨论】:

    【解决方案2】:

    这是可能的,但并不漂亮。对于一些简单但不基于标记语言的语法,我使用下面的正则表达式模板(忘记了源代码)。但在这里也可以正常工作。

             string NestedRegexTemplate =
                @"(?xs)                      # enable eXtended mode (comments/spaces ignored)
                    (?<capturedOpen>{0})                      # start of tag
                    (?'value'                # named capture
                      (?>                    # don't backtrack
                        (?:
                          ((?!{0})(?!{1}).)+             # not tags
                        | (?'open' {0} )       # count opening bracket
                        | (?'close-open' {1} ) # subtract closing bracket (matches only if open count > 0)
                        )*
                      )
                      (?(open)(?!))          # make sure open is not > 0
                    )
                    (?<capturedClose>{1})                        # end of tag
                ";
    
            string test = "<tag id='bold'><tag id='italic'>Hello World</tag></tag>";
            string regex = string.Format(NestedRegexTemplate, @"<\s*tag(\s[^>]*|)>", @"<\s*/\s*tag\s*>");
            var match = Regex.Match(test, regex);
            while (match.Success)
            {
                var capturedOpen = match.Groups["capturedOpen"];
                var capturedClose = match.Groups["capturedClose"];
    
                if (capturedOpen.Value.Contains("'bold'"))
                {
                    test = test.Remove(capturedClose.Index, capturedClose.Length);
                    test = test.Insert(capturedClose.Index, "</b>");
                    test = test.Remove(capturedOpen.Index, capturedOpen.Length);
                    test = test.Insert(capturedOpen.Index, "<b>");
                }
                else if (capturedOpen.Value.Contains("'italic'"))
                {
                    test = test.Remove(capturedClose.Index, capturedClose.Length);
                    test = test.Insert(capturedClose.Index, "</i>");
                    test = test.Remove(capturedOpen.Index, capturedOpen.Length);
                    test = test.Insert(capturedOpen.Index, "<i>");
                }
    
                match = Regex.Match(test, regex);
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 2016-01-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多