我知道有几个类似的问题,但在这个具体案例中找不到任何问题。
我拿了一个代码并根据我的需要调整它,但现在我发现了一个我无法纠正的错误。
代码:
$tag = 'namespace';
$match = Tags::get($f, $tag);
var_dump($match);
static function get( $xml, $tag) { // http://stackoverflow.com/questions/3404433/get-content-within-a-html-tag-using-7-processing
// bug case string(56) "<namespaces>
// <namespace key="-2">Media</namespace>"
$tag_ini = "<{$tag}[^\>]*?>"; $tag_end = "<\\/{$tag}>";
$tag_regex = '/' . $tag_ini . '(.*?)' . $tag_end . '/si';
preg_match_all($tag_regex,
$xml,
$matches,
PREG_OFFSET_CAPTURE);
return $matches;
}
如您所见,如果标记是嵌套的,则存在错误:
<namespaces> <namespace key="-2">Media</namespace>
什么时候应该返回&#39; Media&#39;,甚至是外部的'<namespaces>'
,然后是内部的。{/ p>
我尝试添加&#34; <{$tag}[^\>|^\r\n ]*?>
&#34;,^\s+
,将*更改为*?,以及其他一些最好只能识别出错误案例的事情。
还尝试了"<{$tag}[^{$tag}]*?>"
,它给出了空白,我想它会使自己无效。
我是关于正则表达式的新手,我可以告诉我要解决此问题,只需要添加“不要打开相同类型的新标记”。 或者我甚至可以在我的用例中使用黑客答案,如果内部文本有新的线路运输则排除。
任何人都可以获得正确的语法吗?
您可以在此处查看文字摘录:http://pastebin.com/f2naN2S3
在提议的更改之后:$tag_ini = "<{$tag}\\b[^>]*>"; $tag_end = "<\\/{$tag}>";
它适用于示例案例,但不适用于此案例:
<namespace key="0" />
<namespace key="1">Talk</namespace>
导致:
<namespace key="1">Talk"
这是因为数字和&#34;和字母被认为是在单词边界内。我怎么能解决这个问题?
答案 0 :(得分:1)
这可能不是想法的答案,但我正在搞乱一个正则表达式生成器:
<?php
# URL that generated this code:
# http://txt2re.com/index-php.php3?s=%3Cnamespace%3E%3Cnamespace%20key=%22-2%22%3EMedia%3C/namespace%3E&12&11
$txt='arstarstarstarstarstarst<namespace key="-2">Media</namespace>arstarstarstarstarst';
$re1='.*?'; # Non-greedy match on filler
$re2='(?:[a-z][a-z]+)'; # Uninteresting: word
$re3='.*?'; # Non-greedy match on filler
$re4='(?:[a-z][a-z]+)'; # Uninteresting: word
$re5='.*?'; # Non-greedy match on filler
$re6='(?:[a-z][a-z]+)'; # Uninteresting: word
$re7='.*?'; # Non-greedy match on filler
$re8='((?:[a-z][a-z]+))'; # Word 1
if ($c=preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8."/is", $txt, $matches))
{
$word1=$matches[1][0];
print "($word1) \n";
}
#-----
# Paste the code into a new php file. Then in Unix:
# $ php x.php
#-----
?>
答案 1 :(得分:1)
主要问题是您在开始标记后没有使用字边界,因此模式中的namespace
也可能与namespaces
标记以及许多其他标记匹配。
接下来的问题是,如果有一个自动关闭的<${tag}\b[^>]*>(.*?)<\/${tag}>
标记后面跟着一个&#34;正常&#34;那么namespace
模式就会过火。配对打开/关闭namespace
标记。因此,您需要在(?<!\/)
之前使用否定的lookbehind >
(请参阅demo),或在(?![^>]*\/>)
之后使用\b
否定前瞻(请参阅{ {3}})。
所以,你可以使用
$tag_ini = "<{$tag}\\b[^>]*(?<!\\/)>"; $tag_end = "<\\/{$tag}>";
答案 2 :(得分:0)
这条线是我需要的
$tag_ini = "<{$tag}\\b[^>|^\\/>]*>"; $tag_end = "<\\/{$tag}>";
非常感谢@Alison和@Wictor的帮助和指示