【问题标题】:Extract html attributes from string in PHP [duplicate]从PHP中的字符串中提取html属性[重复]
【发布时间】:2014-06-09 09:20:42
【问题描述】:

我有一个看起来像这样的变量:

$var = '<li data-tpl-classname="class" data-tpl-title="innerHTML"></li>'

我想以某种方式提取 data-tpl-attributes,所以我最终得到一个如下所示的结果数组:

$array = (
    'classname' => 'class',
    'title' => 'innerHTML'
)

“data-tpl-”属性的数量各不相同,并不总是&lt;li&gt; 元素。除此之外,它始终遵循相同的格式:data-tpl-attributename="attributePlacement"

我如何检索这些属性并将它们存储在一个数组中,不使用正则表达式?我说没有正则表达式,因为在我看来,使用正则表达式解析 html 似乎是一种邪恶的做法,或者在这种情况下可以吗?

【问题讨论】:

  • 查看DOMDocument 类。
  • 如果一直是这种形式,您是否尝试过 HTML 或 XML 解析器?
  • @AdrianWragg 不,我没有。不熟悉它。会去看看。

标签: php arrays function parsing dom


【解决方案1】:

您可以使用一些字符串函数来提取值。它看起来像这样:

$test1 = '<li data-tpl-classname="class" data-tpl-title="innerHTML"></li>';
$test2 = '<div data-tpl-anything="something" data-tpl-title="this is a title" data-tpl-third="asdasd"></div>';

var_dump(extract_tpl($test1));
var_dump(extract_tpl($test2));

function extract_tpl($string,$prefix="data-tpl-") {
    $start = 0;
    $end = 0;

    while(strpos($string,$prefix,$end))
    {
        $start = strpos($string,$prefix,$start)+strlen($prefix);
        $end = strpos($string,'"',$start)-1;
        $end2 = strpos($string,'"',$end+2);
        $array[substr($string,$start,$end-$start)] = substr($string,$end+2,$end2-$end-2);
    }

    return $array;
}

输出:

array (size=2)
  'classname' => string 'class' (length=5)
  'title' => string 'innerHTML' (length=9)

array (size=3)
  'anything' => string 'something' (length=9)
  'title' => string 'this is a title' (length=15)
  'third' => string 'asdasd' (length=6)

代码中的数字 (-1, +2, ... ) 用于跳过 " 等符号。

【讨论】:

    【解决方案2】:

    如果不完全是邪恶的,当然,在大字符串或非常复杂的正则表达式上它可能会很慢,这不是你的情况。而且它仍然(更具可读性?),比 HTML 或 XML 解析器更容易和更快地实现,它们并不比简单的正则表达式匹配更优化。

    $var = '<li data-tpl-classname="class" data-tpl-title="innerHTML"></li>'
    preg_match_all("data-tpl-([^"]*)="([^"]*)"/i", $str, $matches);
    
    $array = array();
    for($i = 1, $size = count($matches); $i < $size; ++$i){
      $array[$matches[$i][0]] = $matches[$i][1];
    }
    

    我使用[^"]* 而不是.*?,因为它更快。


    注意:我刚刚做了一个基准测试。与使用 DOMDocument 的第一个答案相比,这段使用 Regexp 的代码快了 4 倍,但由于使用 regexp 解析 Dom 可能会导致对标记的误解,所以更简洁。它比使用str 函数的答案稍慢(但更易于阅读和维护)。

    注意2:当然,只有在不会有任何混淆并且确定输入格式的情况下才使用此解决方案,相反使用DOMDocument的解决方案更干净。


    为什么在解析 HTML 时应该明智地使用或避免使用正则表达式:

    http://blog.codinghorror.com/parsing-html-the-cthulhu-way

    牢记这一点使用它们:

    • 这通常是个坏主意。
    • 除非您有纪律并对您所做的事情提出非常严格的条件,否则将 HTML 与正则表达式匹配会迅速转移 疯狂,这就是克苏鲁喜欢的方式。
    • 我认为在这种特定情况下选择正则表达式的理由是好的、理性的、(半)正当的理由。

    【讨论】:

    • 相比使用 DOMDocument 的第一个答案,这段使用 Regexp 的代码快了 4 倍,我刚刚做了一个基准测试。 你是认真的吗?请不要使用正则表达式来解析 HTML ,您的答案很快就会遭到反对。
    • 您需要知道我只是在谈论哪个运行得快(在这种情况下,仅使用 str 函数的答案会稍微快一些,但更难阅读和维护)。我从来没有说过它更干净,但我不认为它是邪恶的,这完全取决于用例。
    • 我同意,这些是重要的规则: * 这通常是个坏主意。 // * 除非你有纪律并且对你正在做的事情提出非常严格的条件,否则将 HTML 与正则表达式匹配很快就会变成疯狂,这正是 Cthulhu 喜欢的方式。 // * 我有一个我认为好的、理性的、(半)合理的理由在这个特定场景中选择正则表达式。
    【解决方案3】:

    您可以很好地使用 DOMDocument 类,而且不要使用正则表达式。这只是一个开始,您可以很好地探索它。

    <?php
    $var = '<li data-tpl-classname="class" data-tpl-title="innerHTML"></li>';
    echo "<pre>";
    
    function parseTag($content,$tg)
    {
        $dom = new DOMDocument;
        $dom->loadHTML($content);
        $attr = array();
        foreach ($dom->getElementsByTagName($tg) as $tag) {
            foreach ($tag->attributes as $attribName => $attribNodeVal)
            {
               $attr[$attribName]=$tag->getAttribute($attribName);
            }
        }
        return $attr;
    }
    
    $attrib_arr = parseTag($var,'li');
    print_r($attrib_arr);
    

    OUTPUT :

    Array
    (
        [data-tpl-classname] => class
        [data-tpl-title] => innerHTML
    )
    

    Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-09
      • 1970-01-01
      • 1970-01-01
      • 2014-07-17
      • 2016-08-02
      相关资源
      最近更新 更多