preg_match在更改其顺序时与html属性不匹配

时间:2013-06-18 12:48:20

标签: php regex

我正在尝试将某些xml标记与正则表达式匹配 这是我的PHP代码

   $pattern = '#<xt:tag_name *(type\="(.+?)")? *(detail\="(.+?)")? ?/>#ui';
   $str = '<xt:tag_name type="1" detail="2" />';
   preg_replace($pattern,"type: $1, detail: $4",$str);
   preg_match($pattern,$str,$m);
   print_r($m);

我得到了预期的结果

Array
(
    [0] => <xt:tag_name type="1" detail="2" />
    [1] => type="1"
    [2] => 1
    [3] => detail="2"
    [4] => 2
)

但是当我改变属性的顺序时

<xt:tag_name detail="2" type="1" />

匹配失败

1 个答案:

答案 0 :(得分:3)

描述

此正则表达式将捕获属性typedetail,无论属性顺序如何,只要它们位于xt:tag_name标记内。

<xt:tag_name\b(?=\s)(?=(?:(?!\>).)*\s\btype=(["'])((?:(?!\1).)*)\1)(?=(?:(?!\>).)*\s\bdetail=(["'])((?:(?!\3).)*)\3)(?:(?!\>).)*\>

enter image description here

扩展说明

  • <xt:tag_name\b验证标记名称
  • (?=\s)确保标记名称后面有空格
  • (?=预测type的1。通过使用前瞻,您可以按任何顺序捕获属性。
    • (?:(?!\>).)*一次移动标记一个字符并阻止正则表达式引擎退出此标记,直至到达
    • \s\btype=属性type
    • (["'])捕获公开引用,稍后将用于匹配正确的关闭标记
    • ((?:(?!\1).)*)捕获引号内的所有字符,但不包括相同类型的封装引用
    • \1匹配关闭报价
    • )关闭type
    • 的前瞻
  • (?=(?:(?!\>).)*\s\bdetail=(["'])((?:(?!\3).)*)\3)对名为detail的属性执行与type
  • 相同的操作
  • (?:(?!\>).)*匹配所有字符,直到
  • \>标记的结尾

组0将具有从打开到关闭括号的整个标记

  1. 将围绕type值打开引号,这样正则表达式可以正确匹配关闭引用
  2. 将具有属性type
  3. 的值
  4. 将围绕detail值打开引号,这样正则表达式可以正确匹配关闭引用
  5. 将具有属性detail
  6. 的值

    PHP代码示例:

    输入字符串

    <xt:tag_name UselessAttribute="some dumb string" type="1" detail="2" /><xt:tag_name detail="Things 'Punk' Loves" MoreUselessAttributes="1231" type="kittens" />
    

    代码

    <?php
    $sourcestring="your source string";
    preg_match_all('/<xt:tag_name\b(?=\s)(?=(?:(?!\>).)*\s\btype=(["\'])((?:(?!\1).)*)\1)(?=(?:(?!\>).)*\s\bdetail=(["\'])((?:(?!\3).)*)\3)(?:(?!\>).)*\>/ims',$sourcestring,$matches);
    echo "<pre>".print_r($matches,true);
    ?>
    

    匹配

    $matches Array:
    (
    [0] => Array
        (
            [0] => <xt:tag_name UselessAttribute="some dumb string" type="1" detail="2" />
            [1] => <xt:tag_name detail="Things 'Punk' Loves" MoreUselessAttributes="1231" type="kittens" />
        )
    
    [1] => Array
        (
            [0] => "
            [1] => "
        )
    
    [2] => Array
        (
            [0] => 1
            [1] => kittens
        )
    
    [3] => Array
        (
            [0] => "
            [1] => "
        )
    
    [4] => Array
        (
            [0] => 2
            [1] => Things 'Punk' Loves
        )
    )