Posted By

ryanve on 01/31/13


Tagged

parse attributes


Versions (?)

Parse Attributes


 / Published in: PHP
 

URL: http://dev.airve.com/demo/speed_tests/php/parse_attrs.php

Parse an attributes string into an array. If the string starts with a tag, then the attributes on the first tag are parsed. This parses via a manual loop and is designed to be safer than using DOMDocument.

  1. /**
  2.  * Parse an attributes string into an array. If the string starts with a tag,
  3.  * then the attributes on the first tag are parsed. This parses via a manual
  4.  * loop and is designed to be safer than using DOMDocument.
  5.  *
  6.  * @param string|* $attrs
  7.  * @return array
  8.  *
  9.  * @example parse_attrs( 'src="example.jpg" alt="example"' )
  10.  * @example parse_attrs( '<img src="example.jpg" alt="example">' )
  11.  * @example parse_attrs( '<a href="example"></a>' )
  12.  * @example parse_attrs( '<a href="example">' )
  13.  */
  14. function parse_attrs ($attrs) {
  15.  
  16. if ( ! \is_scalar($attrs) )
  17. return (array) $attrs;
  18.  
  19. $attrs = \str_split( \trim($attrs) );
  20.  
  21. if ( '<' === $attrs[0] ) # looks like a tag so strip the tagname
  22. while ( $attrs && ! \ctype_space($attrs[0]) && $attrs[0] !== '>' )
  23. \array_shift($attrs);
  24.  
  25. $arr = array(); # output
  26. $name = ''; # for the current attr being parsed
  27. $value = ''; # for the current attr being parsed
  28. $mode = 0; # whether current char is part of the name (-), the value (+), or neither (0)
  29. $stop = false; # delimiter for the current $value being parsed
  30. $space = ' '; # a single space
  31.  
  32. foreach ( $attrs as $j => $curr ) {
  33.  
  34. if ( $mode < 0 ) {# name
  35. if ( '=' === $curr ) {
  36. $mode = 1;
  37. $stop = false;
  38. } elseif ( '>' === $curr ) {
  39. '' === $name or $arr[ $name ] = $value;
  40. break;
  41. } elseif ( ! \ctype_space($curr) ) {
  42. if ( \ctype_space( $attrs[ $j - 1 ] ) ) { # previous char
  43. '' === $name or $arr[ $name ] = ''; # previous name
  44. $name = $curr; # initiate new
  45. } else {
  46. $name .= $curr;
  47. }
  48. }
  49. } elseif ( $mode > 0 ) {# value
  50. if ( $stop === false ) {
  51. if ( ! \ctype_space($curr) ) {
  52. if ( '"' === $curr || "'" === $curr ) {
  53. $value = '';
  54. $stop = $curr;
  55. } else {
  56. $value = $curr;
  57. $stop = $space;
  58. }
  59. }
  60. } elseif ( $stop === $space ? \ctype_space($curr) : $curr === $stop ) {
  61. $arr[ $name ] = $value;
  62. $mode = 0;
  63. $name = $value = '';
  64. } else {
  65. $value .= $curr;
  66. }
  67. } else {# neither
  68.  
  69. if ( '>' === $curr )
  70. break;
  71. if ( ! \ctype_space( $curr ) ) {
  72. # initiate
  73. $name = $curr;
  74. $mode = -1;
  75. }
  76. }
  77. }
  78.  
  79. # incl the final pair if it was quoteless
  80. '' === $name or $arr[ $name ] = $value;
  81.  
  82. return $arr;
  83. }

Report this snippet  

You need to login to post a comment.