0

我正在尝试检测字符串是 XML/HTML 格式,还是其他格式,如 CSV 或 JSON,可能包含 HTML 作为数据,或者只是可能包含随机 < 或 > 字符的通用文本。我并不是要验证完整的 XML 或 HTML 文档——我正在测试的字符串可能只是 XML/HTML 的片段,或者它们可能是其他东西的片段。因此,我的标准是字符串必须包含至少一个格式正确的 XML 标记,并且该标记必须从字符串的开头开始,除非有任何空格。(此时,您可能已经猜到我正在尝试自动检测文本内容的 mime 类型,然后再将其发送回浏览器。顺便说一句,我在 PHP 中。)

我有一个将检测 XML/HTML 标记的正则表达式:

~<[a-z]+.*?(>.*?</[a-z]+>|/>)~i

我有一个正则表达式,它会告诉我标签是否开始字符串,忽略空格:

~^\s*<~

问题是,我无法弄清楚如何将这两者组合成一个正则表达式。困难似乎源于正则表达式的“贪婪”方面,特别是如果主题包含嵌套标签。帮助?

4

1 回答 1

1

以下示例似乎对我有用:

<?php

$multiline = <<<'EOD'
<html>
<a>Another Tag</a>
</html>
EOD;

$singletag = <<<'EOD'
<html/>
EOD;


$badformat = <<<'EOD'
<html><html>
EOD;

$nothtml = <<<'EOD'
<html><html>
EOD;

$regex = '~^\s*<([a-z\:]+)[^>]*(?:/>|>.*</\1>)~sim';
echo preg_match($regex, $multiline) . "\n"; // 1
echo preg_match($regex, $singletag) . "\n"; // 1
echo preg_match($regex, $badformat) . "\n"; // 0
echo preg_match($regex, $nothtml) . "\n"; // 0

如果您在多行 HTML 上使用它(听起来很可能),那么您没有正确的修饰符

  • s,字符PCRE_DOTALL.包括换行符
  • m for PCRE_MULTILINE,匹配整个文本,不将每一行视为自己的字符串

顺便一提:

  • 我也让这个更严格,所以它必须找到一个匹配的结束标签(使用\1反向引用)
  • 如注释中所述(例如 HTML doctype 或 XML 标头),HTML/XML 文档还有其他有效的开头。正则表达式可能不是最好的解决方案。
  • 您还可以考虑在文件开头要求标签时不要那么严格,或者创建更多规则来为“最佳猜测”文档类型创建分数。
于 2013-09-13T21:47:16.377 回答