miércoles, 7 de agosto de 2013

Extraer información

Los atributos

Aunque ya tenemos definido el método llamado “attributes”, no viene mal tener unos cuantos más para consultar o modificar los contenidos de los atributos. 

Para ello podemos utilizar los operadores de consulta y asignación de índices. Así, para consulta el valor de un atributo tendremos:

def [](index)
  if typeOf != :HTMLTag
   raise "Not a tag"
  end

  return @nodes[@starts_at].attributes[index]
end

Y, para asignarle un valor:

def []=(index, value)
  if typeOf != :HTMLTag
   raise "Not a tag"
  end

  
@nodes[@starts_at].attributes[index] = value
end

Sacando cosas de un documento

Hasta aquí tenemos forma de crear un documento y de obtener información del mismo.

Y también de los elementos que se puedan crear a partir de él. Lo cual estaría muy bien, si no fuera porque aún no sabemos como crear estos elementos.

Eso... ¿Cómo creamos los elementos a partir de un documento?

Bien... buena pregunta... Comencemos por ver como podemos obtener un elemento del documento a partir de su atributo “ID”. Para eso, cuando manipulamos HTML mediante scripts, se suele contar con un método llamado “getElementById”, aplicable a documentos y etiquetas. Su implementación en Ruby para nuestra clase sería:

def getElementById(id)
  if typeOf != :HTMLTag and typeOf != :document
   raise "Not a tag"
  end

  
tagRange.each do |x|
   if @nodes[x].class.name == "HTMLTag" and @nodes[x].attributes['ID'] == id
    return getElement(x)
   end

 end

  return nil
end
  

El método recorre con la variable “x” el rango de nodos correspondiente al objeto actual y, para cada uno de ellos comprueba si se trata de una etiqueta HTML y, de ser así, si su atributo “ID” es igual al que estamos buscando.

Cuando se cumplen estas condiciones, es que hemos dado con lo que estamos buscando. Sólo queda retornar la representación del objeto que comienza en la posición “x” actual.

Pero para eso utilizamos otro método, “getElement” que vamos a dejar para más adelante.

Y con eso van tres métodos que os debo.

Otra cosa interesante sería poder obtener un array, por ejemplo, de todas las etiquetas “<DIV>” de un documento. O de todos los “<li>” subordinados a un determinado “<ul>”. Para cosas como esas podemos definir el siguiente método:

def getElementsByTagName(thetagname)
  return tagRange.select{|x| @nodes[x].class.name == "HTMLTag"

     and @nodes[x].name == thetagname}.collect{|e| getElement(e)}
end

Básicamente, con el “select” miramos dentro del rango de nodos del objeto actual y creamos un array de los valores de x en que aparece una etiqueta con el nombre dado. Posteriormente, a partir de este array, con el “collect” generamos un array de los elementos que empiezan en dichos valores.

Algo parecido podemos hacer para obtener un array de aquellas etiquetas que tengan un determinado atributo igual a un valor dado:

def getElementsByAttribute(attribute, value)
  return tagRange.select{|x| @nodes[x].class.name == "HTMLTag"

     and @nodes[x].attributes[attribute] == value}.collect{|e| getElement(e)}
end

Para ir acabando con esto de generar elementos, podemos crear un array de los nodos hijos de una etiqueta dada o del documento completo como sigue:

def children
 range = tagRange
 
  last_tag = range.last + (typeOf== document ? 1 : 0)
 x = typeOf == :document ? 0 : (range.first + 1)
  result = []
  while x < last_tag
   elemento = getElement(x)
   result.push(elemento)
   x = elemento.ends_at + 1
 end

   
 return result
end
  

Dicho en román paladino: mira dentro de lo que se correspondería con el “innerHTML” y cada vez que encuentres un nodo, añádelo a la lista de resultados, mira donde termina su definición, y continúa buscando a partir de ahí.

No hay comentarios:

Publicar un comentario