jueves, 28 de noviembre de 2024

Python obtener el valor de un nodo de un fichero xml que tiene namespaces

 Queremos extraer el contenido del nodo <ValorBinario> de este fichero xml que namespaces: 

Nos fijamos que el namespace marcado en naranja no tiene nombre, por tanto se aplicará a todas los nodos cuyas etiquetas no tenganprefijo del namespace como "contenido" o "ValorBinario"


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<insidews:documento xmlns="http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido" 
    xmlns:ns2="http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos" 
    xmlns:ns3="http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma" 
    xmlns:ns4="http://www.w3.org/2000/09/xmldsig#" 
    xmlns:ns5="http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e" 
    xmlns:ns6="https://ssweb.seap.minhap.es/Inside/XSD/v1.0/metadatosAdicionales" 
    xmlns:ns7="https://ssweb.seap.minhap.es/Inside/XSD/v1.0/documento-e" 
    xmlns:insidews="https://ssweb.seap.minhap.es/Inside/XSD/v1.0/WebService">
    <ns5:documento Id="ES_L01462384_2022_2_ACORDS_PLE000001">
        <contenido Id="CONTENIDO_DOCUMENTO">
            <ValorBinario>JVB..</ValorBinario>
            <NombreFormato>PDF</NombreFormato>
        </contenido>
        <ns2:metadatos Id="DOC_ES_L01462384_2022_2_ACORDS_PLE000001_METADATOS">
            <ns2:VersionNTI>http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e</ns2:VersionNTI>
            <ns2:Identificador>ES_L01462384_2022_2_ACORDS_PLE000001</ns2:Identificador>
            <ns2:Organo>L01462384</ns2:Organo>
            <ns2:FechaCaptura>2024-11-05T00:00:00.000+01:00</ns2:FechaCaptura>
            <ns2:OrigenCiudadanoAdministracion>true</ns2:OrigenCiudadanoAdministracion>
            <ns2:EstadoElaboracion>
                <ns2:ValorEstadoElaboracion>EE99</ns2:ValorEstadoElaboracion>
            </ns2:EstadoElaboracion>
            <ns2:TipoDocumental>TD02</ns2:TipoDocumental>
        </ns2:metadatos>
        <ns3:firmas>
	   <ns3:firma Id="FIRMA_1">
                <ns3:TipoFirma>TF06</ns3:TipoFirma>
                <ns3:ContenidoFirma>
                    <ns3:FirmaConCertificado>
                        <ns3:ReferenciaFirma xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">#CONTENIDO_DOCUMENTO</ns3:ReferenciaFirma>
                    </ns3:FirmaConCertificado>
                </ns3:ContenidoFirma>
            </ns3:firma>
            <ns3:firma Id="FIRMA_2">
                <ns3:TipoFirma>TF06</ns3:TipoFirma>
                <ns3:ContenidoFirma>
                    <ns3:FirmaConCertificado>
                        <ns3:ReferenciaFirma xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">#CONTENIDO_DOCUMENTO</ns3:ReferenciaFirma>
                    </ns3:FirmaConCertificado>
                </ns3:ContenidoFirma>
            </ns3:firma>
        </ns3:firmas>
    </ns5:documento>
    <ns7:metadatosAdicionales>
        <ns6:MetadatoAdicional tipo="string" nombre="eEMGDE3.1.Nombre.NombreNatural">
            <ns6:valor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">$5.NOM_DOC$</ns6:valor>
        </ns6:MetadatoAdicional>
    </ns7:metadatosAdicionales>
</insidews:documento>


para ello se ha creado este programa python

import base64
from lxml import etree

def extraer_pdf(xml_path, output_pdf_path):
    try:
        # Cargar el archivo XML
        with open(xml_path, "rb") as xml_file:
            xml_data = xml_file.read()
        
        # Parsear el XML
        tree = etree.fromstring(xml_data)
        
        # Definir los namespaces utilizados en el XML
        namespaces = {
            "insidews": "https://ssweb.seap.minhap.es/Inside/XSD/v1.0/WebService",
            "ns5": "http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e",
            "contenido": "http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido"
        }
        
        # Listar nodos para depuración
        print("Nodos disponibles:")
        for elem in tree.iter():
            print(f"{elem.tag}")

        # Buscar el contenido del tag <ValorBinario>
        valor_binario_node = tree.xpath(
            "//insidews:documento/ns5:documento/contenido:contenido/contenido:ValorBinario",
            namespaces=namespaces
        )
        
        if not valor_binario_node:
            raise ValueError("No se encontró el tag <ValorBinario> en el documento XML.")
        
        # Extraer el contenido en Base64
        valor_binario = valor_binario_node[0].text
        
        # Decodificar el contenido Base64
        pdf_data = base64.b64decode(valor_binario)
        
        # Guardar el contenido en el archivo PDF
        with open(output_pdf_path, "wb") as pdf_file:
            pdf_file.write(pdf_data)
        
        print(f"Archivo PDF extraído correctamente y guardado en: {output_pdf_path}")
    
    except Exception as e:
        print(f"Error al procesar el archivo XML: {e}")


# Ruta al archivo XML y al PDF de salida
xml_path = "/home/eduard/MyPython/02.llibreriesOLD/ximo-python-library/ES_L01462384_2022_2_ACORDS_PLE000001.xml"
output_pdf_path = "mifichero.pdf"

# Ejecutar la función
extraer_pdf(xml_path, output_pdf_path)


Y cuando nos lista los nodos aparece

{https://ssweb.seap.minhap.es/Inside/XSD/v1.0/WebService}documento
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e}documento
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido}contenido
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido}ValorBinario
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido}NombreFormato
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}metadatos
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}VersionNTI
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}Identificador
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}Organo
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}FechaCaptura
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}OrigenCiudadanoAdministracion
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}EstadoElaboracion
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}ValorEstadoElaboracion
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/metadatos}TipoDocumental
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}firmas
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}firma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}TipoFirma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}ContenidoFirma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}FirmaConCertificado
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}ReferenciaFirma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}firma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}TipoFirma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}ContenidoFirma
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}FirmaConCertificado
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/firma}ReferenciaFirma
{https://ssweb.seap.minhap.es/Inside/XSD/v1.0/documento-e}metadatosAdicionales
{https://ssweb.seap.minhap.es/Inside/XSD/v1.0/metadatosAdicionales}MetadatoAdicional
{https://ssweb.seap.minhap.es/Inside/XSD/v1.0/metadatosAdicionales}valor

A raiz de todo esto vemos que en el fichero xml, la ruta a <ValorBinario> es:

<insidews:documento><ns5:documento><contenido><ValorBinario>

Por otra parte si reducimos el listado anterior:

{https://ssweb.seap.minhap.es/Inside/XSD/v1.0/WebService}documento
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e}documento
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido}contenido
{http://administracionelectronica.gob.es/ENI/XSD/v1.0/documento-e/contenido}ValorBinario

Vemos que contenido si tiene un namespace que es "contenido" y tambien ValorBinario tiene el namespace "contenido". Por tanto la ruta para llegar a valor binario es:


# Buscar el contenido del tag <ValorBinario>
valor_binario_node = tree.xpath(
   "//insidews:documento/ns5:documento/contenido:contenido/contenido:ValorBinario",
   namespaces=namespaces
)








No hay comentarios :

Publicar un comentario