3ENGINE

Programación y otros cachivaches

Etiqueta: programacion

Página 1/21

Tecnologia

Añadiendo un nuevo espacio de nombres a un árbol XML en Python


Los espacios de nombres en XML son una forma de evitar conflictos de nombres al definir etiquetas personalizadas. En Python, puedes usar la biblioteca xml.etree.ElementTree para trabajar con XML. Sin embargo, trabajar con espacios de nombres puede ser un poco complicado porque necesitas definirlos explícitamente. Este artículo te guiará a través del proceso de cómo añadir un nuevo espacio de nombres a un XML.

Qué es un espacio de nombres en XML?

Un espacio de nombres en XML es una forma de categorizar etiquetas y atributos para evitar conflictos de nombres. Los espacios de nombres son útiles cuando tienes etiquetas personalizadas que podrían entrar en conflicto con las etiquetas estándar de XML. Un espacio de nombres se define con un prefijo y una URI (Uniform Resource Identifier) que suele tomar la forma de una URL.

Añadiendo un nuevo espacio de nombres en Python

Para añadir un nuevo espacio de nombres en Python, primero debes registrar el espacio de nombres usando el método register_namespace() de la biblioteca xml.etree.ElementTree. Este método toma dos argumentos: el prefijo del espacio de nombres y la URI del espacio de nombres. Por ejemplo, puedes registrar un espacio de nombres con el prefijo ‘xsi’ y la URI ‘http://www.w3.org/2001/XMLSchema-instance’ de la siguiente manera:

import xml.etree.ElementTree as ET

ET.register_namespace('xsi', "http://www.w3.org/2001/XMLSchema-instance")

Después de registrar el espacio de nombres, puedes usarlo en tu árbol XML. Por ejemplo, puedes crear un nuevo elemento con el espacio de nombres registrado de la siguiente manera:

root = ET.Element('{http://www.w3.org/2001/XMLSchema-instance}Author'

En este caso, {http://www.w3.org/2001/XMLSchema-instance} es el espacio de nombres que acabamos de registrar

Añadiendo un nuevo espacio de nombres a un XML existente

Si tienes un árbol XML existente y quieres añadir un nuevo espacio de nombres, puedes hacerlo de la siguiente manera:

def addNSToRoot(tree, id, ns):
    root = tree.getroot()

    # add ns
    nsmap = root.nsmap
    if id not in nsmap:
        nsmap[id] = ns

    # create new root tag
    rootNS = etree.Element(root.tag, nsmap=nsmap, **root.attrib)

    # add childrens
    for e in root.iterchildren():
        rootNS.append(e)
    return rootNS

En este caso, la función addNSToRoot toma tres argumentos: el árbol XML, el ID del espacio de nombres y el espacio de nombres en sí. La función obtiene la raíz del árbol XML, verifica si el ID del espacio de nombres ya existe en el mapa de espacios de nombres (nsmap) de la raíz. Si no existe, añade el ID y su correspondiente espacio de nombres al mapa de espacios de nombres. Luego, crea un nuevo elemento raíz con el mismo nombre que la antigua raíz y el nuevo mapa de espacios de nombres. Copia todos los atributos de la antigua raíz al nuevo elemento. Finalmente, añade todos los hijos de la antigua raíz al nuevo elemento raíz y devuelve el nuevo elemento raíz

Ejemplo de uso:

tree = etree.parse('file.xml')
root = addNSToRoot(tree, 'sc', 'http://schemas.microsoft.com/3dmanufacturing/securecontent/2019/04')



Tecnologia

Agrupar metodos en clases de Python.


Imaginemos que tienes una clase Class1 con una buena colección de métodos. Para facilitar su uso quieres agrupar los métodos, de modo que tendrias esto:

c = Class1(param1, param2)
c.colors.green()
c.colors.yellow()
c.animals.bird()
c.animals.mouse()
etc..

Ademas necesitas que los metodos tengan acceso a los datos de la clase padre.

Para agrupar métodos en clases de Python, puedes utilizar clases internas (o anidadas). Estas clases se definen dentro del cuerpo de otra clase. Si se crea un objeto utilizando una clase, el objeto dentro de la clase raíz puede ser utilizado. Una clase puede tener una o más clases internas. Si quieres que los métodos de las clases internas tengan acceso a los datos de la clase padre, puedes hacerlo pasando self a la clase interna.

Aquí un ejemplo de cómo hacerlo:

class Class1:
   def __init__(self, param1, param2):
       self.param1 = param1
       self.param2 = param2
       self.colors = self.Colors(self)
       self.animals= self.Animals(self)

   class Colors:
       def __init__(self, parent):
           self.parent = parent

       def green(self):
           print("green")
           print(self.parent.param1)

       def yellow(self):
           print("yellow")
           print(self.parent.param2)

   class Animals:
       def __init__(self, parent):
           self.parent = parent

       def bird(self):
           print("bird")
           print(self.parent.param1)

       def mouse(self):
           print("mouse")
           print(self.parent.param2)



Tecnologia

PlatformIO: cómo cambiar la versión del compilador


Para cambiar la versión del compilador de C++11 a C++17 en PlatformIO, necesitas modificar la sección build_flags en tu archivo de configuración de PlatformIO. Aquí un ejemplo de cómo quedaria tu archivo de configuración:

[platformio]
default_envs = az-delivery-devkit-v4

[common]
build_flags =
    -std=gnu++17
build_unflags =
    -std=gnu++11

[env:az-delivery-devkit-v4]
    monitor_speed = 115200
    platform = espressif32
    board = az-delivery-devkit-v4
    framework = arduino
lib_deps =
    olikraus/U8g2@^2.35.4
    igorantolic/Ai Esp32 Rotary Encoder@^1.6
    esphome/ESP32-audioI2S@^2.0.7
build_flags =
    ${common.build_flags}
build_unflags =
    ${common.build_unflags}

En el fragmento anterior, -std=gnu++17 le indica al compilador que utilice la versión C++17 del estándar de C++. Por otro lado, -std=gnu++11 se utiliza para desactivar el uso de C++11. Estos flags se aplican a tu entorno de compilación az-delivery-devkit-v4

Cambiar a una versión más reciente del lenguaje C++, como por ejemplo C++17, tiene ventajas:

  • Nuevas características del lenguaje: Cada nueva versión de C++ introduce nuevas características del lenguaje que pueden hacer que tu código sea más eficiente, fácil de entender y robusto. Por ejemplo, C++17 introdujo características como std::optional y std::variant que pueden ayudar a manejar mejor los casos en los que una variable puede o no tener un valor.
  • Mejoras del compilador: A medida que se desarrolla una nueva versión del estándar de C++, los compiladores también mejoran, tu código se compila más rápido y se ejecuta más eficientemente.
  • Compatibilidad con bibliotecas más recientes: Algunas bibliotecas solo son compatibles con versiones más recientes.
  • Estandarización: Te aseguras de que estás utilizando un estándar que ha sido revisado y aprobado por la comunidad de C++. Esto puede hacer que tu código sea más confiable y fácil de entender para otros desarrolladores.



Tecnologia

Cómo imprimir una lista de forma más agradable en Python por línea de comandos


A menudo en Python necesitamos imprimir una lista por la línea de comandos. La manera mas habitual y sencilla es imprimir los elementos de la lista separados por comas. Por ejemplo:

Código

fruit_list = ['Albaricoque', 'Cereza', 'Ciruela', 'Higo', 'Kaki', 'Manzana', 'Melocoton', 'Nectarina',
              'Nispero', 'Pera', 'Uva', 'Aguacate', 'Carambola', 'Chirimoya', 'Coco', 'Datil', 'Fresa',
              'Fruta de la pasion', 'Kiwi', 'Litchi', 'Mango', 'Papaya', 'Platano', 'Grosella negra']

print ','.join(fruit_list)

Resultado

Aguacate, Albaricoque, Carambola, Cereza, Chirimoya, Ciruela,.....

Pero yo encuentro que no es muy legible para el usuario. Voy a dejar aquí una pequeña función que imprime por línea de comandos la lista formateada en columnas, ordenando los elementos alfabéticamente. A la función se le pasa por parámetro la lista (obvio) y el número de columnas que deseas. Como parámetro opcional (con un valor por defecto de 2) se puede indicar el espacio entre columnas. Para un ajuste óptimo, la función calcula el espacio que necesita para cada una de las columnas.

Código

def print_sorted_list(data, columns, gap=2):
    if data:
        gap = 2
        ljusts = {}
        for count, item in enumerate(sorted(data), 1):
            column = count % columns
            ljusts[column] = len(item) if (column not in ljusts) else max(ljusts[column], len(item))

        for count, item in enumerate(sorted(data), 1):
            print item.ljust(ljusts[count % columns] + gap),
            if (count % columns == 0) or (count == len(data)):
                print

Demo

fruit_list = ['Albaricoque', 'Cereza', 'Ciruela', 'Higo', 'Kaki', 'Manzana', 'Melocoton', 'Nectarina',
              'Nispero', 'Pera', 'Uva', 'Aguacate', 'Carambola', 'Chirimoya', 'Coco', 'Datil', 'Fresa',
              'Fruta de la pasion', 'Kiwi', 'Litchi', 'Mango', 'Papaya', 'Platano', 'Grosella negra']

print_sorted_list(fruit_list, columns=3)

Resultado

Aguacate             Albaricoque      Carambola
Cereza               Chirimoya        Ciruela
Coco                 Datil            Fresa
Fruta de la pasion   Grosella negra   Higo
Kaki                 Kiwi             Litchi
Mango                Manzana          Melocoton
Nectarina            Nispero          Papaya
Pera                 Platano          Uva

Saludos.