2009-07-05 5 views
7

Tengo una cadena con atributos HTML:PHP - dividir una serie de atributos HTML en una matriz indexada

$attribs = ' id= "header " class = "foo bar" style ="background-color:#fff; color: red; "'; 

cómo transformar esa cadena en una matriz indexada, como:

array(
    'id' => 'header', 
    'class' => array('foo', 'bar'), 
    'style' => array(
    'background-color' => '#fff', 
    'color' => 'red' 
) 
) 

para que pueda usar la función PHP array_merge_recursive para fusionar 2 conjuntos de atributos HTML.

Gracias

Respuesta

8

Se podría utilizar una expresión regular para extraer esa información:

$attribs = ' id= "header " class = "foo bar" style ="background-color:#fff; color: red; "'; 
$pattern = '/(\\w+)\s*=\\s*("[^"]*"|\'[^\']*\'|[^"\'\\s>]*)/'; 
preg_match_all($pattern, $attribs, $matches, PREG_SET_ORDER); 
$attrs = array(); 
foreach ($matches as $match) { 
    if (($match[2][0] == '"' || $match[2][0] == "'") && $match[2][0] == $match[2][strlen($match[2])-1]) { 
     $match[2] = substr($match[2], 1, -1); 
    } 
    $name = strtolower($match[1]); 
    $value = html_entity_decode($match[2]); 
    switch ($name) { 
    case 'class': 
     $attrs[$name] = preg_split('/\s+/', trim($value)); 
     break; 
    case 'style': 
     // parse CSS property declarations 
     break; 
    default: 
     $attrs[$name] = $value; 
    } 
} 
var_dump($attrs); 

Ahora sólo tiene que analizar las clases de class (dividida en espacios en blanco) y declaraciones de bienes de style (una un poco más difícil ya que puede contener comentarios y URLs con ; en él).

+0

Gracias Gumbo, su expresión regular es genial El único problema es que $ attrs ['class'] o $ attrs ['style'] están devolviendo cadenas: por lo que será difícil fusionarlos con otra cadena de $ attribs, por ejemplo, fusionando esos 2 conjuntos de atributos: $ attribs1 = 'clase = "barra foo"'; $ attribs2 = 'clase = "lorem"'; en una 'clase =' foo bar lorem '' Por eso me gustaría que $ attrs ['clase'] devuelva una matriz: array ('foo', 'bar') ¿Tiene una idea para mejorar esto? ? – abernier

+0

Realmente me encanta esta solución ... pero no obtengo la expresión regular xD es un poco para mi cabeza – lumio

+1

Acabo de escribir una expresión regular alternativa que también analiza atributos booleanos de estilo HTML5 (sin un signo =) y utiliza una referencia para las comillas: '(\ w +) \ s * (= \ s * ([" ']) (. *?) \ 2 \ s)? ' –

2

Puede ser que esto le ayuda .. Lo que hace ..

  • Un analizador DOM HTML escrito en PHP5 + permiten manipular HTML de una manera muy fácil!
  • Requiere PHP 5+.
  • Admite HTML no válido.
  • Encuentra etiquetas en una página HTML con selectores como jQuery.
  • Extraiga el contenido de HTML en una sola línea.

http://simplehtmldom.sourceforge.net/

+0

Tenga en cuenta que la única razón por la que terminé aquí es porque DOMProcessingInstruction tiene un campo 'data' que es el texto con' '. En el caso de una etiqueta como: '' obtienes una cadena simple como: 'type =" text/xsl "href =" https://sms.m2osw.com/sitemap.xsl "' que debe analizar como atributos. –

3

no puede utilizar una expresión regular para analizar html atributos. Esto se debe a que la sintaxis es contextual. Puede usar expresiones regulares para tokenizar la entrada, pero necesita una máquina de estados para analizarla.

Si el rendimiento no es un gran problema, la forma más segura de hacerlo es, probablemente, ajustar los atributos en una etiqueta y luego enviarla a través de un analizador html. Ej .:

function parse_attributes($input) { 
    $dom = new DomDocument(); 
    $dom->loadHtml("<foo " . $input. "/>"); 
    $attributes = array(); 
    foreach ($dom->documentElement->attributes as $name => $attr) { 
    $attributes[$name] = $node->value; 
    } 
    return $attributes; 
} 

Probablemente podría optimizar lo anterior, mediante la reutilización del analizador, o mediante el uso de XmlReader o la sax parser.

+0

Analizar esto: foo = 'bar' cuux = "O'Reiley" zip = "\ zap \" " – troelskn

+0

@troelskn: La tercera declaración de valor de atributo no es válida. La' 'necesidad para ser representado por referencias de personaje. – Gumbo

+0

Tienes razón, no era consciente de eso. Aún así, sugeriría usar un analizador xml/html para dar cuenta de todo tipo de casos de bordes impares. – troelskn

17

Uso SimpleXML:

<?php 
$attribs = ' id= "header " class = "foo bar" style ="background-color:#fff; color: red; "'; 

$x = new SimpleXMLElement("<element $attribs />"); 

print_r($x); 

?> 

Esto supone que los atributos son siempre pares nombre/valor ...

1

manera fácil podría ser también:

 
$atts_array = current((array) new SimpleXMLElement("<element $attribs />")); 
Cuestiones relacionadas