如何编写正则表达式以匹配没有子元素的XML元素的任何非空内容?

时间:2009-12-11 02:01:36

标签: c# .net xml regex whitespace

我正在尝试匹配没有其他子元素的元素,但也有内容。没有内容也包括空白和& nbsp;字符。我需要在C#中执行此操作。

以此XML为例:

<1>
    <2><3 /></2>
    <4>
        <5>This is match 1</5>
    </4>
    <6>     
         </6>
    <7>    &nbsp;&nbsp;&nbsp;&nbsp;    &nbsp;&nbsp;&nbsp;</7>
    <8>This is match 2</8>
</1>

因此只有元素5和8匹配。其余的元素有子元素或“空格”(空格,制表符,回车符,新行,&amp; nbsp;)

注意

SLaks发布:

“通常,您不能使用正则表达式解析XML。 而是使用System.Xml命名空间。“

遗憾的是,在这种情况下这是不可行的。这是一个不是由我的团队制作的应用程序,我们需要优化它而不重写任何东西(不是我的决定)。 这是无效的XML ,因此我需要这样做以使其有效。然后我可以将其视为xml :)

换句话说,它是一个非常类似于XML的字符串。

这是我到目前为止所提出的,除了“空白”排除外,其他所有内容都被排除在外:

  Regex ElementExpression = new Regex(
      @"<(?'tag'\w+?).*>" + // match first tag, and name it 'tag'
      @"(?'text'[^<>]*[\\S]+?)" + // match text content, name it 'text'
      @"</\k'tag'>" // match last tag, denoted by 'tag'
      , RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase);

6 个答案:

答案 0 :(得分:2)

一般来说,you must not parse XML using regular expressions

相反,请使用System.Xml命名空间。

答案 1 :(得分:1)

这方面的正则表达式非常麻烦。基本上你需要一个寻找平衡对LinK的正则表达式,并且在平衡对中你想要任何对你的场景有效的东西。 “对你的场景有效是一个糟糕的部分。鉴于你展示的片段你想要一个类似于的正则表达式:

<(?<tag>\w*)>(?<text>.*)</\k<tag>> 

(由Expresso提供)

(?<text>.*) <- is what you will have to construct by hand to match your elim criteria

答案 2 :(得分:1)

我不会使用正则表达式来做到这一点!我会通过Tidy实用程序运行它,然后使用XSLT和XPath。

答案 3 :(得分:0)

通过使用一个正则表达式来获取元素,我能够得到我想要的东西,第二个正则表达式可以删除我定义的空格。

大约30MB的数据需要3秒钟。

  Regex ElementExpression = new Regex(
            @"<(?'tag'\w+?)(?'attributes'.*?)>" + // match first tag, and name it 'tag'
            @"(?'text'[^<>]*?)" + // match text content, name it 'text'
            @"</\k'tag'>" // match last tag, denoted by 'tag'
            , RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase);


  Regex WhiteSpaceExpression = new Regex(@"\A((&nbsp;)|(\s)|(\r))*\Z", RegexOptions.Multiline | RegexOptions.Compiled | RegexOptions.IgnoreCase);

  text = ElementExpression.Replace(text, delegate(Match match){
        if (match.Groups.Count > 0){
           Group textGroup = match.Groups["text"];
           if (!WhiteSpaceExpression.IsMatch(textGroup.Value)){
              return String.Format("<{0}{1}>{2}</{0}>", match.Groups["tag"].Value, match.Groups["attributes"].Value, HttpUtility.HtmlEncode(textGroup.Value));
           }
           else{
              return String.Format("<{0}{1} />", match.Groups["tag"].Value, match.Groups["attributes"].Value);
           }
        }
        return match.Value;
  });

答案 4 :(得分:0)

如果不是XML那么糟糕。说它是一个“密切代表XML的字符串”并不是对问题的充分定义。字符串非常类似于XML,并且为一个字符串设计的解析解决方案无法与另一个一起使用。

如果您可以具体说明字符串与XML的偏离方式 - 即,如果您能够识别原始开发人员在尝试编写XML时所犯的特定错误 - 应该可以撤消损坏,将字符串转换为格式良好的XML,然后使用DOM方法查找您正在查找的数据。

如果你不能具体说明字符串偏离XML的方式,那么你遇到的问题比编写正则表达式要大得多。

答案 5 :(得分:-1)

我会在两次传球中接近它。 (在perl中,但正则表达式应该翻译。)

第一遍。提取所有字符串。

my @strings = $s =~ /<[^>]+>([^<>]+)<[^/>]*/[^/>]*>/g;

第二关。过滤掉不需要的

@strings = grep {!/&nbsp;|^\s+$/} @strings;