Migración de bases ISIS a KOHA

Cuestiones preliminares

Para que cualquiera de los métodos descritos a continuación funcione, es imprescindible completar algunos pasos previos. Estos pasos se refieren a la configuración del sistema e incluyen, en orden de importancia, los siguientes parámetros:

item types (tipos de item): Son las categorías a las que pertenecen los ejemplares que maneja de biblioteca. Por ejemplo, los videocassettes pertenecen a una categoría distinta a la de los libros y a la de las grabaciones sonoras. Este paso es fundamental, ya que mucha de la funcionalidad de Koha se pierde si no se especifican correctamente los tipos de ítem.

MARC tag structure (Estructura de campos MARC): Koha permite definir qué campos MARC serán usados y cuáles serán ignorados. La importancia de este paso radica en la posibilidad de establecer una correlación entre los subcampos MARC y los campos de las tablas presentes en Koha.

Como ejemplo, la posible estructura para los subcampos del campo de título, 245:

Ver código fuente SQL y resultado

SELECT tagsubfield,kohafield FROM marc_subfield_structure WHERE tagfield=245;
 +-------------+-------------------------+
 | tagsubfield | kohafield               |
 +-------------+-------------------------+
 | 6           |                         |
 | 8           |                         |
 | a           | biblio.title            |
 | b           | bibliosubtitle.subtitle |
 | c           |                         |
 | f           |                         |
 | g           |                         |
 | h           | biblio.abstract         |
 | k           |                         |
 | n           |                         |
 | p           |                         |
 | s           |                         |
 +-------------+-------------------------+

Aproximaciones

Hay más de una aproximación al problema de la migración de datos de una base existente a las bases del sistema Koha, si bien no todas se enfocan a la migración de datos contenidos en bases ISIS. Las siguientes secciones muestran los distintos caminos analizados y tratan de anticipar los problemas que pueden presentar cada uno de ellos.

ISIS -> XML -> TEXT -> MARC -> KOHA

Este método consiste, tal como describe su autor en su página web, en exportar una base de datos ISIS a un archivo XML a través de la utilidad incluida a tal efecto en WinISIS.

Nota: La utilidad mencionada se encuentra en el menú 'Utils' de WinIsis, pero sólo es accesible si el idioma seleccionado es el inglés. Por alguna razón desconocida, si se configura el idioma de WinIsis a español, la opción no es visible en el menú.

A partir de este archivo XML, se utiliza un script escrito en Python, el cual genera un archivo de texto delimitado por tabulaciones ('tab delimited text file').

A continuación, se transforma la información contenida en el archivo de texto en registros MARC mediante otro script, éste escrito en lenguaje Perl.

Finalmente, el archivo conteniendo los registros en formato MARC se importaría a las bases de Koha. El autor no especifica la manera en que esta importación se realiza, pero se infiere la utilización del script bulkmarcimport.pl provisto en la ditribución de Koha (ubicado en Linux en: DirectorioDeKoha/scripts/misc/).

Este método no ha sido probado hasta el momento, debido a que es el más complejo de los tres analizados, en cuanto a la cantidad de pasos necesarios

ISIS -> ISO -> ISO2709 -> KOHA

Este método no está presente en una página web, ni ha sido propuesto en la lista de correo de Koha, sino que se deriva de la posibilidad, ofrecida por el propio Koha, de realizar una importación masiva de datos a las bases que componen el sistema a través del script bulkmarcimport.pl (ubicado en Linux en: DirectorioDeKoha/scripts/misc/).

Este script recibe como parámetro, entre otras cosas, la ubicación y el nombre de un archivo ISO2709 que contenga los datos MARC que se quieran importar.

La dificultad que se presenta a la hora de migrar bases ISIS a Koha, es que el archivo ISO generado por las distintas herramientas disponibles no es interpretado correctamente, ya que no se atendría lo suficiente al estándar ISO2709.

Poco antes de la elaboración de este informe, se realizaron pruebas con la utilidad ImpExp disponible en http://www.unesco.org/isis/files/winisis/windows/utilities/. Mediante esta utilidad sería posible transformar un archivo ISO generado a partir de una base ISIS en un archivo ISO conforme al estándar ISO2709.

Las pruebas realizadas hasta el momento no han sido satisfactorias, pero es necesario continuar con las mismas para obtener una conclusión determinante.

ISIS -> TEXT -> MARC -> KOHA

Este método ha sido probado con bastante éxito y aprovecha la versatilidad del lenguaje de formateo de ISIS, para la generación de un archivo de texto con la estructura de campos y los valores de los mismos en un “MARC Anotado”, que es básicamente un archivo de texto que puede ser abierto con MarcEdit, para su conversión final a MARC. Finalmente, se usa el script bulkmarcimport.pl (ubicado en Linux en: DirectorioDeKoha/scripts/misc/)

Obviamente, este método involucra un trabajo previo de análisis de la base de datos y las correspondencias entre los campos que la componen y los campos del formato MARC, además de una serie de idas y vueltas (prueba y error) hasta contar con un archivo MARC de una calidad, por lo menos, aceptable. Esto se hace indispensable si se tiene en cuenta que el script bulkmarcimport.pl sirve para poblar la base de Koha con datos externos, pero no para actualizarlos si ya se encuentran presentes. En otras palabras, lo mejor es asegurarse de que la información contenida en el archivo MARC sea lo más correcta posible, antes de realizar la importación final.

  1. Revisión: Revisar y revisar otra vez las asociaciones entre campos MARC y campos KOHA en la parte de administración de Koha
  2. Crear PFT: Crear un archivo PFT que muestre el contenido de la base ISIS de una forma similar a la siguiente:
    =LDR 00000nam\\2200000\a\4500
    =020 \\$a9505044631
    =092 \\$a636(038) C152
    =100 \\$aTweeten, Luther G.$d1919-1999
    =245 10$aGlosario inglés castellano de términos usados en producción
    animal.
    =650 04$aDiccionario Técnico
    =650 04$aInglés
    =650 04$aEspañol
    =650 04$aSilvicultura
    =650 04$aProducción forestal
    =650 04$aAlnus
    =650 04$aProducción Animal
    =653 \\$aAliso
    =942 \\$cBK
    =952 \\$pOAG13849$bOAG$dOAG
    

    Obviamente, nuestro registros CDS/ISIS no tienen “leader” (cabecera) y les falta alguna información que es necesaria en KOHA, como por ejemplo, el 'itemtype' o el código de Biblioteca (en este ejemplo, en Koha está definida como Branch la Biblioteca de Ciencias Agrarias con el código 'OAG' y hemos definido que al 'barcode' de cada libro se le agregue el código de biblioteca, para diferenciarlo de los 'barcodes' de las demás bibliotecas)\\La salida anterior se puede obtener con un archivo .pft como el que sigue:\\

    '=LDR 00000nam\\\\2200000\\a\\4500'/
    (|=020 \\\\$a|v010/)/
    |=092 \\\\|v075/
    (|=100 \\\\$a|,v28^a/)/
    |=110 \\\\$a|,v29^p,if p(v29^s) then |$b|v29^s fi/
    |=111 \\\\$a|,v40^n/
    |=245 \\\\$a|v24^t,if p(v24^s) then | : $b|v24^s fi/
    |=591 \\\\$a|,v59/
    (|=650 \\\\$a|,v65/)/
    (|=653 \\\\$a|,v62/)/
    '=942 \\\\$cBK'/
    (|=952 \\\\$pOAG|v77|$bOAG$dOAG|/)
    |=999 \\\\$a|,v999/
    ##
    

    En la sección Apéndice se encuentra este mismo código, con comentarios acerca de lo que realiza cada instrucción.

  3. Impresión: Imprimir la base de datos ISIS usando el archivo PFT en un documento de texto.
    Nosotros usamos WinISIS para esta tarea, porque permite imprimir un rango de registros, o los resultados de una búsqueda (por ejemplo, buscamos todos los registros que tienen presente un número de inventario, y sólo imprimimos esos registros, para no importar analíticas de revistas).
    Dentro de las opciones de impresión de WinISIS, definimos qué queremos imprimir (rango o resultado de búsqueda), cambiamos, obviamente, la impresora por defecto por la opción de “archivo de texto (ANSI de Windows)” (hay una opción ASCII de DOS, pero esa trae problemas con los acentos y demás caracteres especiales) y finalmente cambiamos el archivo PFT por defecto por nuestro archivo PFT creado en el paso 1.
    Al darle la orden de imprimir, WinISIS presentará un cuadro de diálogo para seleccionar el nombre y la ubicación del archivo de texto generado.Para hacer el proceso más fácil, lo mejor es darle un nombre y agregarle la extensión '.mrk'
  4. Editar el archivo de texto con MARCEdit: Una vez completado el volcado de la base, se podrá editar el archivo .mrk creado con WinISIS con la herramienta MARCEdit. Básicamente, lo que haremos con esta herramienta será, en primer lugar, buscar y reemplazar todos los símbolos '^' que delimitan subcampos en ISIS por '$' que delimitan subcampos en MARC.
    Terminado el reemplazo, sólo resta utilizar la función de 'Compilar archivo MARC' o 'crear archivo MARC' (el nombre y la ubicación de esta función ha ido cambiando entre versiones de MARCEdit) que básicamente transforma este archivo de texto .mrk en un archivo binario .mrc
  5. Importar registros en Koha vía bulkmarcimport.pl. La sintaxis para esto sería básicamente:
    ./bulkmarcimport.pl -file /home/marc_files/oun.mrc
    

    pero se puede hacer una corrida de prueba antes agregando -t y -v 1 o -v 2 \\

    ./bulkmarcimport.pl -file /home/marc_files/oun.mrc -t -v 2
    

ISIS -> XML -> KOHA

Este método, en pocas palabras, implica la exportación de una base ISIS a un archivo XML y la utilización de una script Perl para la inclusión de los datos contenidos en el archivo XML directamente a las bases de datos de Koha.

Para la concreción exitosa de este método es necesaria la generación de un archivo XML bien formado con todos los datos de la base de datos ISIS que se quiera importar a Koha. El autor del mismo recomienda la utilización de la herramienta ISIS2XML disponible en ftp://ftp.unesco.org/pub/winisis/windows/utilities/Isis2XML/

Sin embargo, este soft sólo se encuentra disponible en francés. Por lo tanto, si bien el autor (del método y los scripts, no del soft) también ha puesto a disposición de cualquier interesado una serie de imágenes que describen el proceso de creación del archivo XML (que se descargan junto con el script). Las pruebas se realizaron haciendo modificaciones al lenguaje de formateo de ISIS utilizado por WinIsis para generar archivos XML a partir de una base de datos.

Es imprescindible que el XML resultante no contenga 'saltos de linea' (carriage returns) ya que, de lo contrario, el script de importación generará un error y abortará.

El archivo XML utilizado en las pruebas se generó por medio de la utilidad de impresión de WinIsis, configurando la salida a un archivo de texto y utilizando el formato presentado en el Apéndice. Se debe recordar que la estructura de un archivo XML debe contar con un elemento raíz. Este elemento raíz se generó colocando <BASE> como Header y </BASE> como Footer, en la ventana de configuración de la impresión de WinIsis.

Instalación

El script de migración requiere la instalación previa de una serie de módulos de PERL:

Term::Activity
DBD::mysql
XML::Twig
MARC::Record

Posteriormente, el script necesitará saber dónde se encuentran los módulos de Koha. Por ejemplo, si la instalación de Koha se encuentra en /usr/local/koha/ el comando a ejecutar sería:

$ export PERL5LIB=/usr/local/koha/intranet/modules

Con los pasos anteriores sería suficiente para que el script pueda funcionar correctamente. Se puede probar lo anterior ubicándose en el directorio en el que se encuentra el script y ejecutando el comando:

$./xml2koha.pl -pf data/10-records.xml

El resultado de este comando es un 'dump' en pantalla del contenido de 10 registros de prueba (contenidos en el archivo 10-records.xml) en formato MARC.

Configuración

Para lograr que el script se comporte correctamente, se debe configurar su funcionamiento. Esto se logra editando dos archivos de texto, que acompañan al script ejecutable, de nombres xml2koha.conf y xml2koha.map

xml2koha.conf

Se trata de un archivo de configuración bastante simple en el cual se debe setear las siguientes variables:

$MAPFILE: El nombre del archivo de texto conteniendo el mapeado entre etiquetas XML y campos/subcampos MARC.

$RECORD_ELEMENT: El nombre de la etiqueta XML que contiene la información de cada registro de la base ISIS a importar en Koha.

Como ejemplo, si la estructura XML es:

<REGISTRO>
   <TAG_1>aaaaaa</TAG_1>
   <TAG_2>bbbbbb</TAG_2>
   <TAG_3>cccccc</TAG_3>
</REGISTRO>

En xml2koha.conf debería figurar:

$RECORD_ELEMENT = “REGISTRO”;
$DEFAULT_TAGS : Definición de campos que se agregarán a cada registro procesado, con un contenido fijo.
xml2koha.map

El archivo xml2koha.map es creado por el script xml2koha.pl automáticamente (si se cambia el valor de $MAPFILE en xml2koha.conf el nombre del archivo .map también cambiará). Para lograr esto, el archivo XML creado a partir de la base ISIS (supongamos datos-cdsisis.xml) debe ser colocado en el mismo directorio del script xml2koha.pl. El comando para realizar este proceso es:

 $ ./xml2koha.pl -mf datos-cdsisis.xml

Completado este comando, quedará, en el mismo directorio, un nuevo archivo .map que SERÁ NECESARIO EDITAR MANUALMENTE (no hay otra forma) para hacer coincidir las etiquetas encontradas en el archivo XML con campos/subcampos MARC.

Al abrir el archivo .map con un editor de texto, se observarán dos secciones. La primera la compone una serie de comentarios referidos a la cantidad de ocurrencias de las distintas etiquetas encontradas en el archivo XML. Esto puede servir como un primer punto de control.

La segunda sección está compuesta de líneas del tipo…

 000 ## %TAG

…que es donde se especifica el mapeado deseado.

Los tres números iniciales deben ser reemplazados con el campo MARC de destino, al cual irá a parar la información contenida en cada etiqueta <TAG> Los dos ## encontrados a continuación, deberán ser reemplazados, si es necesario, por los valores de los indicadores que deberán incluirse en el campo/subcampo MARC de destino. A continuación se podrá especificar el subcampo MARC al cual irá a parar la información contenida en cada etiqueta <TAG>, lo cual se logra colocando un signo $ seguido de la etiqueta de subcampo. Finalmente, se coloca el nombre del elemento/etiqueta XML del que se extraerá la información, para el campo/subcampo MARC especificado. Este elemento puede ser precedido por: % : Sirve para mezclar, en un mismo campo MARC, la información proveniente de varios campos. En la base de destino, se mezclaran los contenidos de los campos de la base ISIS que apunten al mismo campo/subcampo MARC. @ : Un elemento/etiqueta que comience con este símbolo será repetible. Cada elemento enviado desde la base ISIS al mismo campo/subcampo MARC, será colocado en una nueva ocurrencia en la base MARC de destino. Un archivo xml2koha.map de ejemplo se ha incluido en este documento. La estructura de este archivo debería quedar más o menos como sigue:


# Some counts of Elements found in data/vidunc.xml
# Count		Element/Tag Name
# 3		Tag_110_a
# 5		Tag_245_a
# 5		Tag_245_n
# 9		Tag_653_a

110 ## $a %Tag_110_a
245 ## $a %Tag_245_a
245 ## $n %Tag_245_n
653 ## $a @Tag_653_a

Una vez que se está conforme con la configuración, se puede probar el resultado con el comando:

$ ./xml2koha.pl -pf datos-cdsisis.xml

La opción -p presenta los resultados solamente en pantalla.

Para insertar los datos en la instalación de Koha, se deberá ejecutar el siguiente comando:

 $ ./xml2koha.pl -cf datos-cdsisis.xml

En el caso de que se haya producido un error o se haya cometido una equivocación, se podrá eliminar todos los datos bibliográficos de las base de Koha, antes de arreglar el problema y realizar una nueva importación, con el siguiente comando:

 $ ./xml2koha.pl -dcf datos-cdsisis.xml

Los ajustes y reconfiguraciones sucesivas se harán inevitables y el proceso de conversión se vuelve bastante lento cuando se realiza la migración de una gran cantidad de registros, por lo que se aconseja realizar las pruebas con conjuntos reducidos de registros, entre 30 y 50, hasta que el resultado sea el esperado.

Apéndice

ISIS -> XML -> TEXT -> MARC -> KOHA

Script Python (XML -> TEXT)

ciddtf.py : Convert ISIS Document Database to Text File

Before Parsing :

Change RECORDX\xc3\x91_5\xc3\xaf\x03\x12 to RECORD

Change & to and

fix problems of <Tag_97> manualy.

Ver código fuente

import libxml2
record = []
def Record(i, node):
    sub_node = node.children
    while sub_node is not None:
    if sub_node.type == "element":
    record[i][sub_node.name] = sub_node.get_content()
    sub_node = sub_node.next
    else:
    sub_node = sub_node.next
 
    Memory debug specific 
libxml2.debugMemory(1) 
 
isis_data = libxml2.parseFile ('../xmls/docs.xml')
root = isis_data.getRootElement()
node = root.children
i = 0
while node is not None:
    if node.type != "element":
    node = node.next
    continue
    if node is None:
    break
    if node.name == "RECORD":
    ##print node.get_content()
    record.append({})
    Record(i, node)
    i = i + 1
    node = node.next
    else:
    print "unhandled node in <isis_xml>: " + node.name
isis_data.freeDoc()
 
Memory debug specific 
libxml2.cleanupParser() 
 
if libxml2.debugMemory(1) == 0:
    print "OK"
else:
    print "Memory leak %d bytes" % (libxml2.debugMemory(1))
    libxml2.dumpMemory()
record_file = open('../outs/docs.txt', 'w')
tag = ['Tag_4', 'Tag_7', 'Tag_11', 'Tag_12', 'Tag_13', 'Tag_18', 'Tag_19', 'Tag_20', 'Tag_21', 'Tag_24', 'Tag_38', 'Tag_10', 'Tag_114', 'Tag_115', 'Tag_110', 'Tag_5', 'Tag_122', 'Tag_97', 'Tag_151', 'Tag_153', 'Tag_123']
for j in record:
    if j.has_key('Tag_691'):
    record_file.write(j['Tag_691'])
 
Check docs without 114 tag 
if j.has_key('Tag_114'): 
    pass 
else: 
    print j['Tag_691'] 
else: 
record_file.write('_B_L_A_N_K_')
    for h in tag:
    if j.has_key(h):
    record_file.write('\t'+j[h])
    else:
    record_file.write('\t_B_L_A_N_K_')
    record_file.write('\n')

Script Perl (TEXT -> MARC)

Ver código fuente Perl

package cmftf;
    Create MARC From Text File 
Copyright 2004 Baiju M <baijum81@lycos.com> 
This program is licensed under GNU GPL. 
use strict;
use MARC::Record;
my $input_file = "../outs/docs.txt";
my $output_file = "../outs/docs.out";
my $repeated_items = " ";
open(INFILE, $input_file) or die "Can't open $input_file: $!";
open(OUTFILE, ">>", $output_file) or die "Can't open $output_file: $!";
my $c = 0;
while (<INFILE>) {
    $c++;
    my $biblionumber_ftf_691_090_c, my $title_ftf_4_245_a, my $edition_ftf_7_250_a, my $publisher_ftf_11_260_b, my $publishcountry_ftf_12_260_a, my $publishyear_ftf_13_260_c, my $author1ee_ftf_18_100_a, my $author1se_ftf_19_100_a, my $author2ee_ftf_20_700_a, my $author2se_ftf_21_700_a, my $adiauthors_ftf_24_700_a, my $role_ftf_38_590_a, my $phydescr_ftf_10_300_a, my $classno_ftf_114_852_k, my $classno_ftf_115_852_h, my $keyword_ftf_5_520_a, my $voldetails_ftf_110_440_v, my $dateofentry_ftf_122_952_v, my $notes_ftf_97_500_a, my $pubprice_151_952_r, my $currency_153_590_b, my $reccreated_123_508_a, my $remainder;
    ($biblionumber_ftf_691_090_c, $title_ftf_4_245_a, $edition_ftf_7_250_a, $publisher_ftf_11_260_b, $publishcountry_ftf_12_260_a, $publishyear_ftf_13_260_c, $author1ee_ftf_18_100_a, $author1se_ftf_19_100_a, $author2ee_ftf_20_700_a, $author2se_ftf_21_700_a, $adiauthors_ftf_24_700_a, $role_ftf_38_590_a, $phydescr_ftf_10_300_a, $classno_ftf_114_852_k, $classno_ftf_115_852_h, $keyword_ftf_5_520_a, $voldetails_ftf_110_440_v, $dateofentry_ftf_122_952_v, $notes_ftf_97_500_a, $pubprice_151_952_r, $currency_153_590_b, $reccreated_123_508_a, $remainder) = split(/\t/, $_, 23);
    if (($biblionumber_ftf_691_090_c !~ /[^\d]/) and ($title_ftf_4_245_a !~ /_B_L_A_N_K_/) and ($repeated_items !~ /$biblionumber_ftf_691_090_c/) ) {
    $repeated_items .= " $biblionumber_ftf_691_090_c";
    my @biblionumber_array;
    open(INF, $input_file) or die "Can't open $input_file: $!";
    my $i = 1;
    while (<INF>) {
    $i++;
    if ($i >= $c) {
    my $biblionumber_ftf_691_090_c2, my $title_ftf_4_245_a2, my $edition_ftf_7_250_a2, my $publisher_ftf_11_260_b2, my $publishcountry_ftf_12_260_a2, my $publishyear_ftf_13_260_c2, my $author1ee_ftf_18_100_a2, my $author1se_ftf_19_100_a2, my $author2ee_ftf_20_700_a2, my $author2se_ftf_21_700_a2, my $adiauthors_ftf_24_700_a2, my $role_ftf_38_590_a2, my $phydescr_ftf_10_300_a2, my $classno_ftf_114_852_k2, my $classno_ftf_115_852_h2, my $keyword_ftf_5_520_a2, my $voldetails_ftf_110_440_v2, my $dateofentry_ftf_122_952_v2, my $notes_ftf_97_500_a2, my $pubprice_151_952_r2, my $currency_153_590_b2, my $reccreated_123_508_a2, my $remainder2;
    ($biblionumber_ftf_691_090_c2, $title_ftf_4_245_a2, $edition_ftf_7_250_a2, $publisher_ftf_11_260_b2, $publishcountry_ftf_12_260_a2, $publishyear_ftf_13_260_c2, $author1ee_ftf_18_100_a2, $author1se_ftf_19_100_a2, $author2ee_ftf_20_700_a2, $author2se_ftf_21_700_a2, $adiauthors_ftf_24_700_a2, $role_ftf_38_590_a2, $phydescr_ftf_10_300_a2, $classno_ftf_114_852_k2, $classno_ftf_115_852_h2, $keyword_ftf_5_520_a2, $voldetails_ftf_110_440_v2, $dateofentry_ftf_122_952_v2, $notes_ftf_97_500_a2, $pubprice_151_952_r2, $currency_153_590_b2, $reccreated_123_508_a2, $remainder2) = split(/\t/, $_, 23);
    if (($biblionumber_ftf_691_090_c2 !~ /[^\d]/) and ($title_ftf_4_245_a2 !~ /_B_L_A_N_K_/) and ($title_ftf_4_245_a2 eq $title_ftf_4_245_a) and ($author1ee_ftf_18_100_a2 eq $author1ee_ftf_18_100_a)){
    print "$biblionumber_ftf_691_090_c:$biblionumber_ftf_691_090_c2\t";
    $repeated_items .= " $biblionumber_ftf_691_090_c2";
    push @biblionumber_array, $biblionumber_ftf_691_090_c2;
    }
    }
    }
    print "\n";
    close(INF);
    my $record = MARC::Record->new();
    if ($author1ee_ftf_18_100_a =~ /_B_L_A_N_K_/) {
    $author1ee_ftf_18_100_a = "";
    }
    if ($author1se_ftf_19_100_a =~ /_B_L_A_N_K_/) {
    $author1se_ftf_19_100_a = "";
    }
    my $author1_ftf = join(" ", $author1se_ftf_19_100_a, $author1ee_ftf_18_100_a);
    if ($author1_ftf ne "") { 
my $author1 = MARC::Field->new(
    '100','1','',
    a => $author1_ftf
    );
    $record->add_fields($author1);
    }
    if ($title_ftf_4_245_a !~ /_B_L_A_N_K_/) { 
my $title = MARC::Field->new(
    '245','1','2',
    a => $title_ftf_4_245_a
    );
    $record->add_fields($title);
    }
    if ($edition_ftf_7_250_a !~ /_B_L_A_N_K_/) { 
my $edition = MARC::Field->new(
    '250',,,
    a => $edition_ftf_7_250_a
    );
    $record->add_fields($edition);
    }
    if ($publishcountry_ftf_12_260_a !~ /_B_L_A_N_K_/) { 
my $publishcountry = MARC::Field->new(
    '260',,,
    a => $publishcountry_ftf_12_260_a
    );
    $record->add_fields($publishcountry);
    }
    if ($publisher_ftf_11_260_b =~ /_B_L_A_N_K_/) {
    $publisher_ftf_11_260_b = "";
    }
    if ($publishyear_ftf_13_260_c =~ /_B_L_A_N_K_/) { 
$publishyear_ftf_13_260_c = "";
    }
    my $publisher = MARC::Field->new(
    '260',,,
    b => $publisher_ftf_11_260_b,
    c => $publishyear_ftf_13_260_c
    );
    $record->add_fields($publisher);
    if ($phydescr_ftf_10_300_a =~ /_B_L_A_N_K_/) {
    $phydescr_ftf_10_300_a = "";
    }
    my $phydescr = MARC::Field->new(
    '300',,,
    a => $phydescr_ftf_10_300_a,
    f => 'BOOK'
    );
    $record->append_fields($phydescr);
    if ($voldetails_ftf_110_440_v !~ /_B_L_A_N_K_/) { 
my $voldetails = MARC::Field->new(
    '440','','3',
    v => $voldetails_ftf_110_440_v
    );
    $record->add_fields($voldetails);
    }
    if ($notes_ftf_97_500_a !~ /_B_L_A_N_K_/) { 
my $notes = MARC::Field->new(
    '500',,,
    a => $notes_ftf_97_500_a
    );
    $record->add_fields($notes);
    }
    if ($reccreated_123_508_a !~ /_B_L_A_N_K_/) { 
my $reccreated = MARC::Field->new(
    '508',,,
    a => $reccreated_123_508_a
    );
    $record->add_fields($reccreated);
    }
    if ($keyword_ftf_5_520_a !~ /_B_L_A_N_K_/) { 
my $keyword = MARC::Field->new(
    '520',,,
    a => $keyword_ftf_5_520_a
    );
    $record->add_fields($keyword);
    }
    if ($role_ftf_38_590_a =~ /_B_L_A_N_K_/) { 
$role_ftf_38_590_a = '';
    }
    if ($currency_153_590_b =~ /_B_L_A_N_K_/) {
    $currency_153_590_b = '';
    }
    my $role = MARC::Field->new(
    '590',,,
    a => $role_ftf_38_590_a,
    b => $currency_153_590_b
    );
    $record->add_fields($role);
    if ($author2ee_ftf_20_700_a =~ /_B_L_A_N_K_/) {
    $author2ee_ftf_20_700_a = "";
    }
    if ($author2se_ftf_21_700_a =~ /_B_L_A_N_K_/) {
    $author2se_ftf_21_700_a = "";
    }
    if ($adiauthors_ftf_24_700_a =~ /_B_L_A_N_K_/) {
    $adiauthors_ftf_24_700_a = "";
    }
    my $adiauthors_ftf = join(" ", $author2se_ftf_21_700_a, $author2ee_ftf_20_700_a, $adiauthors_ftf_24_700_a);
    if ($adiauthors_ftf ne "") { 
my $adiauthors = MARC::Field->new(
    '700','1','',
    a => $adiauthors_ftf
    );
    $record->add_fields($adiauthors);
    }
    if ($classno_ftf_114_852_k =~ /_B_L_A_N_K_/) {
    if ($classno_ftf_115_852_h =~ /_B_L_A_N_K_/) {
    my $classno = MARC::Field->new(
    '852',,,
    k => '999.9999'
    );
    $record->add_fields($classno);
    }
    else {
    if ($classno_ftf_115_852_h =~ /^\d\d\d/) {
    my $classno = MARC::Field->new(
    '852',,,
    k => $classno_ftf_115_852_h
    );
    $record->add_fields($classno);
    }
    else {
    my $classno = MARC::Field->new(
    '852',,,
    k => '999.9998',
    h => $classno_ftf_115_852_h
    );
    $record->add_fields($classno);
    }
    }
    } 
else {
    if ($classno_ftf_114_852_k =~ /^\d\d\d/) {
    if ($classno_ftf_115_852_h =~ /_B_L_A_N_K_/) {
    $classno_ftf_115_852_h = "";
    }
    my $classno = MARC::Field->new(
    '852',,,
    k => $classno_ftf_114_852_k,
    h => $classno_ftf_115_852_h
    );
    $record->add_fields($classno);
    }
    else {
    if ($classno_ftf_115_852_h =~ /^\d\d\d/) {
    my $classno = MARC::Field->new(
    '852',,,
    k => $classno_ftf_115_852_h,
    h => $classno_ftf_114_852_k
    );
    $record->add_fields($classno);
    }
    else {
    if ($classno_ftf_115_852_h =~ /_B_L_A_N_K_/) {
    $classno_ftf_115_852_h = "";
    }
    my $classno = MARC::Field->new(
    '852',,,
    k => '999.9997',
    h => $classno_ftf_115_852_h
    );
    $record->add_fields($classno);
    }
    }
    }
    if ($pubprice_151_952_r =~ /_B_L_A_N_K_/) { 
$pubprice_151_952_r = '';
    }
    if ($dateofentry_ftf_122_952_v =~ /_B_L_A_N_K_/) {
    $dateofentry_ftf_122_952_v = '';
    }
    my @biblionumber_array_tmp = sort @biblionumber_array;
    foreach (@biblionumber_array_tmp) {
    my $biblionumber = $_;
    my $barcode = MARC::Field->new(
    '952',,,
    b => "MAIN",
    d => "MAIN",
    p => $biblionumber,
    r => $pubprice_151_952_r,
    u => $biblionumber,
    v => $dateofentry_ftf_122_952_v
    );
    $record->add_fields($barcode);
    }
    #print "\n";
    print OUTFILE $record->as_usmarc();
    }
    else {
    #print $_;
    }
    }

ISIS -> TEXT -> MARC -> KOHA

PFT comentado


'=LDR  00000nam\\\\2200000\\a\\4500'/

Esta línea imprime un pseudo-leader. El leader de este ejemplo es siempre el mismo en todos los registros. Puede editarse para armar uno a partir de la información presente en cada registro.

A partir de aquí, la idea es que se imprima en cada línea lo siguiente:

=<Nro de campo MARC> \\\\[identificador de subcampo]<Contenido del campo ISIS>

Por ejemplo, la siguiente linea…


(|=020  \\\\$a|v010/)/

… imprime

=20 \\\\$a(Contenido del campo 10 en la base ISIS)

Nota: hay que tener en cuenta cuándo los campos son repetibles. En el caso anterior, el campo 10 en ISIS es repetible, por lo que la línea completa se coloca entre parentesis y así se imprime un '=20 $a' por cada ocurrencia del campo 10.

La siguiente línea imprime el contenido de nuestra signatura topográfica que está en el campo 75 de ISIS en el 092 de MARC


|=092  \\\\|v075/

esta línea imprime el contenido de nuestro campo autor, que está en el campo 28 de ISIS, en el 100 de MARC


(|=100  \\\\$a|,v28^a/)/

El resto de las líneas hacen un trabajo similar, para el resto de los campos.


|=110  \\\\$a|,v29^p,if p(v29^s) then |$b|v29^s fi/
|=111  \\\\$a|,v40^n/
|=245  \\\\$a|v24^t,if p(v24^s) then | : $b|v24^s fi/
|=591  \\\\$a|,v59/
(|=650  \\\\$a|,v65/)/
(|=653  \\\\$a|,v62/)/

De aquí en adelante empieza lo fundamental, para que la importación funcione correctamente…

Koha, por defecto, espera encontrar al momento de la importación el tipo de item (itemtype) en el campo 942 subcampo c de la base que se está importando. (Esto se puede cambiar, en la sección de Preferencias del Sistema)


'=942  \\\\$cBK'/

Además, también espera encontrar

  • en el campo 952 subcampo p → los códigos de barra de cada item
  • en el campo 952 subcampo b → el codigo de la biblioteca propietaria del libro (homebranch)
  • en el campo 952 subcampo d → el codigo de la biblioteca en la que se encuentra el libro (holdingbranch)

(|=952  \\\\$pOAG|v77|$bOAG$dOAG|/)

ISIS -> XML -> KOHA

Script Perl (XML -> KOHA)

Ver código fuente Perl

 
#!/usr/bin/perl
 
use strict;
package xml2koha;
 
use vars qw( $opt_m $opt_v $opt_c $opt_f $opt_p $opt_d $opt_q);
use Getopt::Std;
 
use XML::Twig;
# use XML::Checker::Parser;
use MARC::Record;
 
use C4::Context;
use C4::Biblio;
 
use Term::Activity;
 
&usage() unless getopts('mvpdcqf:'); 
&usage() unless $opt_f;
 
# get configuration settings
do "xml2koha.conf";
 
my $xml_file = $opt_f;
 
our $ldr = &make_leader();
our $tag_008 = &make_008();
 
our %tags;
our %map;
 
our $marc_rec = MARC::Record->new();
our $dbh = C4::Context->dbh;
 
our $ta; # $ta->tick;
 
die "Can't find '$xml_file': $!\n" unless -f $xml_file;
 
# always go into quiet mode when printing MARC to STDOUT
$opt_q = 1 if $opt_p;    
 
if( $opt_v ) {
    # validate the XML
    # print "Validating XML file..." unless $opt_q;
    # validate($xml_file);
    # print "done\n" unless $opt_q;
}
 
if( $opt_m ) {
    # make XML to MARC map file
    print "Making XML to MARC map..." unless $opt_q;
    make_map($xml_file);
    print "done\n" unless $opt_q;
}
 
if ($opt_d) {
    # remove any trace of previous records in koha db
        print "Deleting biblios..." unless $opt_q;
        $dbh->do("delete from biblio");
        $dbh->do("delete from biblioitems");
        $dbh->do("delete from items");
        $dbh->do("delete from bibliosubject");
        $dbh->do("delete from additionalauthors");
        $dbh->do("delete from bibliosubtitle");
        $dbh->do("delete from marc_biblio");
        $dbh->do("delete from marc_subfield_table");
        $dbh->do("delete from marc_word");
        $dbh->do("delete from marc_blob_subfield");
    print "done\n" unless $opt_q;
}
 
if( $opt_p ) {
    # always go into quiet mode when printing MARC to STDOUT
    $opt_q = 1;    
 
    # print to STDOUT in a human readable format
    convert($xml_file);
 
    # don't run convert when printing as well
    $opt_c = 0;
 
}
 
if( $opt_c ) {
    #convert to MARC
    $xml2koha::ta = new Term::Activity({label => 'records imported'}) 
        unless $opt_q;
    convert($xml_file);
}
 
 
################### validate ###########################
# Check that this XML file survives parsing
########################################################
#sub validate {
#    my($xml_file) = @_;        
#    my %expat_options = (KeepCDATA => 1,
#                         SkipExternalDTD => 1
#                         );
#
#    my $xp = new XML::Checker::Parser(%expat_options);
#    eval {
#        local $XML::Checker::FAIL = \&my_fail;
#        $xp->parsefile($xml_file);
#    };
#    if ($@) {
#        print "$xml_file failed validation!\n";
#        die "$@";
#    }
#}
 
################ my_fail ##############################
# I can't get ISIS2XML to produce a DTD so in all cases
# please ignore undefined element (101) and 
# attribute (103) errors.
#######################################################
sub my_fail {
    my $code = shift;
    if($code > 109) {
        die XML::Checker::error_string ($code, @_) if $code < 200;
        XML::Checker::print_error ($code, @_);
    }
}
 
####################### make_map #######################
# make a map file for the user.  The map file will 
# translate xml elements into marc tags
########################################################
sub make_map {
    my($xml_file,) = @_;
    my $twig = new XML::Twig(
                             keep_spaces => 1,                            
                             TwigHandlers => { $xml2koha::RECORD_ELEMENT => \&map_record }
                             );
    $twig->parsefile($xml_file);
 
    if(-f $xml2koha::MAPFILE) {
        return(0) unless &y_or_n(
          "The map file ($xml2koha::MAPFILE) already exists.
Are you sure you wish to overwrite it?"); 
    }
 
    open(MAPFILE,"> $xml2koha::MAPFILE") || 
        die "Can't open output '$xml2koha::MAPFILE':$!\n";
 
    print MAPFILE "#\n# XML to MARC mapping derived from $xml_file\n#\n\n";
 
    print MAPFILE "# Some counts of Elements found in $xml_file\n";
    print MAPFILE "# Count\t\tElement/Tag Name\n";
    foreach my $tag (sort keys(%xml2koha::tags)) {
        my $count = $xml2koha::tags{$tag};
        print MAPFILE "# $count\t\t$tag\n";
    }
 
    print MAPFILE "\n\n";
    foreach my $tag (sort keys(%xml2koha::tags)) {
        my $count = $xml2koha::tags{$tag};
        print MAPFILE "000 ## \%$tag\n";
    }
}
 
##################### map_record #######################
# Collect all the elements in each record.  While I'm 
# collecting them I might as well count how many of 
# each element is in the XML file.  All the tags or 
# elements will be stored in the tags array.
########################################################
sub map_record {
    my($twig, $record) = @_;
    my $el  = $record->first_child();
    if($el) {
        do {
            my $name = $el->gi;
            $xml2koha::tags{$name}++;
        } while( $el = $el->next_sibling());
    }
    $twig->purge;
}
 
################### make_leader ########################
# make a leader tag (LDR or 000)
########################################################
sub make_leader {
 
    # an example leader
    #           1         2
    # 012345678901234567890123
    # *****nam##22*****#a#4500
 
                      # 012345678901234567890123
    my @ldr = split(//,'************************');
    $ldr[5]  = 'n';         # new item
    $ldr[6]  = 'a';         # language material. ie book
    $ldr[7]  = 'm';         # it's a monograph
    $ldr[8]  = '#';         # No specific type 
    $ldr[9]  = '#';         # MARC-8
    $ldr[10] = '2';         # indicators are 2 chars
    $ldr[11] = '2';         # subfields are 2 chars
    $ldr[17] = '5';         # Partial (preliminary) level
                               # Look, the previous db is a mess
    $ldr[18] = '#';         # Non-ISBD
    $ldr[19] = '#';         # Related record not required
    $ldr[20] = '4';         # spec just says put these numbers in
    $ldr[21] = '5';        
    $ldr[22] = '0';
    $ldr[23] = '0';
    return join('',@ldr);
}
 
##################### make_008 #########################
# make a 008 field for my books
########################################################
sub make_008 {
 
    # an example 008 tag
    #           1         2         3
    # 0123456789012345678901234567890123456789
    # 820305s1991####nyu###########001#0#eng##
 
                          # 0123456789012345678901234567890123456789
    my @tag_008 = split(//,'########################################');
 
    my ($day, $month, $year) = (localtime)[3,4,5];
 
    # date marc record was created
    my @date_str = split(//,(sprintf("%02d%02d%02d",
                            ($year+1900) % 100,$month+1,$day)));
    for(my $i = 0; $i <= 5; $i++) { $tag_008[$i] = $date_str[$i]; }
 
    # 008/07-10 (Date 1) and 008/11-14 (Date 2)
    # no date specified
    $tag_008[6] = 'b';
 
    # Place of publication, production, or execution
    # No attempt to code this
    # 15..17
    for(my $i = 15; $i <= 17; $i++) { $tag_008[$i] = '|'; }
 
    # book related info
    # 18..34
    for(my $i = 18; $i <= 34; $i++) { $tag_008[$i] = '|'; }
 
    # language of material
    # once again, no attempt made
    # 35..37
    for(my $i = 35; $i <= 37; $i++) { $tag_008[$i] = '|'; }
 
    # Modified record    
    # No attempt 
    $tag_008[38] = '|';
 
    # Cataloging source
    # No attempt
    $tag_008[39] = '|';
 
    return join('',@tag_008);
}
 
################# convert ##############################
# Convert the CML to Koha DB records
########################################################
sub convert {
    my($xml_file) = @_;
    %xml2koha::map = &get_map($xml2koha::MAPFILE);
 
    my $twig = new XML::Twig(
                            TwigHandlers => { 
                                $xml2koha::RECORD_ELEMENT => \&convert_record }
                             );
     $twig->parsefile($xml_file); 
}
 
############### convert_record #########################
# twig handler.  Called every time a new record is 
# processed
########################################################
sub convert_record {
    my($twig, $record) = @_;
    my %items;
 
    my $mfn = $record->att("MFN");
 
    $xml2koha::ta->tick unless $opt_q;
 
    $xml2koha::marc_rec = MARC::Record->new();
 
    # set the leader for the record
    $xml2koha::marc_rec->leader($xml2koha::ldr);
 
    # set the 008 tag since we're dealing with books
    my $field = MARC::Field->new('008',$xml2koha::tag_008);
    $xml2koha::marc_rec->append_fields($field);
 
    # add default tags from config file
    $xml2koha::marc_rec->add_fields(@{$xml2koha::DEFAULT_TAGS});
 
    my $el = $record->first_child();
    if($el) {
        do {
            my $key = $el->gi();
            my $value = $el->text();
            # these symbols cause havoc in web-based systems so dump
            # them.
            $value =~ s/<//;
            $value =~ s/>//;
            $items{$key} = $value;
            &add_field($key,$value);
        } while( $el = $el->next_sibling());
    }
 
    # add the MFN
    if($mfn) {
        # check whether a 952 tag already exists
        if(my $field = $xml2koha::marc_rec->field('952')) {
            # if so then add a p subfield
            $field->update('p' => $mfn);
        } else {
            # if not then make a new 952 tag
            my $field = MARC::Field->new('952','','','p' => $mfn);
        }
    }
 
    # only print to STDOUT if that is what you asked
    print $xml2koha::marc_rec->as_formatted(), "\n" if $opt_p;
 
    # When in print mode don't save to koha
    &koha_save unless $opt_p;
 
    # try and be tidy by deleting this twig when done
    $twig->purge;
}
 
################# add_field ############################
# gather XML elements and make them fields in a 
# MARC::Record
########################################################
sub add_field {
    my($xml_element,$element_value) = @_;
    my $tag;
    my $indicator_1;
    my $indicator_2;
    my $subfield;
    my %fields;
    my $merge;
 
    # first get all the required values for this xml element out of
    # map defined by the user
 
    $tag         = $xml2koha::map{$xml_element}->{'tag'};
    $indicator_1 = $xml2koha::map{$xml_element}->{'indicator_1'};
    $indicator_2 = $xml2koha::map{$xml_element}->{'indicator_2'};
    $subfield    = $xml2koha::map{$xml_element}->{'subfield'};    
    $merge       = $xml2koha::map{$xml_element}->{'merge'};
 
    # check whether this tag has already been inserted.  If not then
    # it won't be a merge.
    if(!$xml2koha::marc_rec->field($tag)) {
        $merge = 0;
        # no matter what, we have a new tag so make the subfields hash
        # straight away
        %fields = ($subfield => $element_value);
    }
 
    if($merge) {
        # The tag already exists so get the subfields hash and 
        # add or append new subfields.
        if(my $text = $xml2koha::marc_rec->field($tag)->subfield($subfield)) {
            # update the subfield
            $text .= ' ' . $element_value;
            $xml2koha::marc_rec->field($tag)->update($subfield => $text);
        }
        else {
            # add a new subfield
            $xml2koha::marc_rec->field($tag)->add_subfields($subfield,
                                                            $element_value);  
        }
        # The tag already exists so check whether indicators should
        # be updated or added or left alone
        if(my $ind1 = $xml2koha::marc_rec->field($tag)->indicator(1)) {
            # update an indicator
            if($indicator_1 =~ m/\d/) {
                if($ind1 !~ m/\d/) { 
                    $xml2koha::marc_rec->field($tag)->
                        update(ind1 => $indicator_1);
                };
            }
        }
        else {
            # add a new indicator
            $xml2koha::marc_rec->field($tag)->
                update(ind1 => $indicator_1);              
        }
 
        # The tag already exists so check whether indicators should
        # be updated or added or left alone
        if(my $ind2 = $xml2koha::marc_rec->field($tag)->indicator(2)) {
            # update an indicator
            if($indicator_2 =~ m/\d/) {
                if($ind2 =~ m/\#/) { 
                    $xml2koha::marc_rec->field($tag)->
                        update(ind2 => $indicator_2);
                };
            }
        }
        else {
            # add a new indicator
            $xml2koha::marc_rec->field($tag)->
                update(ind2 => $indicator_2);  
        }
 
    }
    else {
        # always add fields that are not merged together.
        # tag 650 for example.
        my $field = MARC::Field->new($tag,
                                     $indicator_1,
                                     $indicator_2,
                                     $subfield => $element_value);
        $xml2koha::marc_rec->append_fields($field);
    }
}
 
################# koha_save ############################
# Write the MARC::Record into koha db
########################################################
sub koha_save {
    # $record = MARC::File::USMARC::decode(char_decode($record->as_usmarc(),$char_encoding));
    # warn "$i ==>".$record->as_formatted() if $verbose eq 2;
    my ($tagfield,$tagsubfield) = 
        &MARCfind_marc_from_kohafield($dbh,"items.itemnumber");
    my @fields = $xml2koha::marc_rec->field($tagfield);
    my @items;
    my $nbitems=0;
 
    foreach my $field (@fields) {
        my $item = MARC::Record->new();
        $item->append_fields($field);
        push @items,$item;
        $xml2koha::marc_rec->delete_field($field);
        $nbitems++;
    }
 
    # now, create biblio and items with NEWnewXX call.
    my ($bibid,$oldbibnum,$oldbibitemnum) = NEWnewbiblio($dbh,$xml2koha::marc_rec);
    for (my $i=0;$i<=$#items;$i++) {
        NEWnewitem($dbh,$items[$i],$bibid);
    }
 
}
 
################ get_map ###############################
# returns an associative array of the tags, indicators 
# and subfields defined by the user
########################################################
sub get_map {
    my($infile) = @_;
    my %tags;
    my $sub_field;
    my $data;
 
    open(INFILE,$infile) || die "Can't open input '$infile':$!\n";
    while(<INFILE>) {
        chomp;        # ditch the end of line marker
        s/^\s*//;     # ditch the leading spaces
        s/\s*$//;     # ditch the trailing spaces
 
        # might just be a blank line as well
        next if length == 0;
 
        # is the line a comment.  if so then skip it
        next if /^\s*#/;
 
        # always start with a blank row
        my %row = ();
 
        # split the line using a space as the delimiter 
        my ($tag,$indicators,$the_rest) = split(/ /,$_,3);
        $row{'tag'} = $tag;
        ($row{'indicator_1'},$row{'indicator_2'}) = split(//,$indicators);
 
        # check for sub fields
        if($the_rest =~ /^\s*\$/) {
            ($sub_field,$data) = split(/ /,$the_rest,2);
            $row{'subfield'} = substr($sub_field,1);
            $row{'data'} = substr($data,1);
 
            # if the field starts with a % then this will be merged with
            # the same tag / subfield
            if($data =~ /\%./) {$row{'merge'} = 1;}
            else { $row{'merge'} = 0; }
        }
        else {
            $row{'data'} = substr($the_rest,1);
 
            # if the field starts with a % then this will be merged with
            # the same tag / subfield
            if($data =~ /\%./) { $row{'merge'} = 1; }
            else { $row{'merge'} = 0; }
        }
 
        # gather all my rows together
        $tags{substr($data,1)} = \%row;
 
    }   
    # share my rows with evriwun else
    return %tags;
}
 
################ y_or_n ###############################
# Simple prompter
#######################################################
sub y_or_n {
    my($prompt) = @_;
    print STDOUT $prompt;
    my $answer = scalar(<STDIN>);
    $answer =~ /^y/i;
}
 
################ usage ################################
# Tell the user how to run me
#######################################################
sub usage {
print "
USAGE:
xml2koha.pl -mvcdpqf filename
 
    -m map
       Makes a map file in the current directory called 
       xml2koha.map
 
    -v validates the XML file used for input
 
    -c converts the XML file to MARC
 
    -d Deletes all bibliographic records in the Koha DB 
 
    -p Print to STDOUT only.  Do not write records into koha.
       Use this option to test the process and revised map file
 
    -q Quiet mode.  Don't advise me of what is going on
 
    -f Sets the XML file used for input.  You'll to set 
       this everytime the program is run.
";
exit(); 
}

Lenguaje de Formateo (PFT)

El siguiente es el lenguaje de formateo ISIS utilizado para generar un archivo XML con los datos de la base que se importarán a KOHA.

mhu  "<REGISTRO>""<Tag_1>"d1,if v1*0.1<>'^' then v1^* fi "</Tag_1>"d1,"<Tag_3_a>"v3^a"</Tag_3_a>""<Tag_3_b>"v3^b"</Tag_3_b>""<Tag_3_c>"v3^c"</Tag_3_c>"d3"<Tag_5>"d5 if v5*0.1<>'^' then v5^* fi "</Tag_5>"d5,"<Tag_6>"d6,if v6*0.1<>'^' then v6^* fi "</Tag_6>"d6,"<Tag_8>"d8 if v8*0.1<>'^' then v8^* fi "</Tag_8>"d8,"<Tag_10>"d10 if v10*0.1<>'^' then v10^*  fi "</Tag_10>"d10,"<Tag_11>"d11 if v11*0.1<>'^' then v11^* fi "</Tag_11>"d11,"<Tag_14_a>"v14^a"</Tag_14_a>""<Tag_14_b>"v14^b"</Tag_14_b>"d14,"<Tag_15>"d15  if v15*0.1<>'^' then v15^* fi "</Tag_15>"d15,"<Tag_20_t>"v20^t"</Tag_20_t>""<Tag_20_s>"v20^s"</Tag_20_s>""<Tag_22_a>"v22^a"</Tag_22_a>"d22,"<Tag_23_s>"v23^s"</Tag_23_s>""<Tag_23_p>"v23^p"</Tag_23_p>""<Tag_23_c>"v23^c"</Tag_23_c>""<Tag_23_i>"v23^i"</Tag_23_i>"d23,"<Tag_24_t>"v24^t"</Tag_24_t>""<Tag_24_s>"v24^s"</Tag_24_s>"d24,"<Tag_27>"d27, if v27*0.1<>'^' then v27^* fi "</Tag_27>"d27,"<Tag_28_a>"v28^a"</Tag_28_a>""<Tag_28_c>"v28^c"</Tag_28_c>""<Tag_28_f>"v28^f"</Tag_28_f>"d28,"<Tag_29_p>"v29^p"</Tag_29_p>""<Tag_29_s>"v29^s"</Tag_29_s>""<Tag_29_t>"v29^t"</Tag_29_t>""<Tag_29_o>"v29^o"</Tag_29_o>""<Tag_29_f>"v29^f"</Tag_29_f>"d29,"<Tag_30_t>"v30^t"</Tag_30_t>""<Tag_30_s>"v30^s"</Tag_30_s>"d30,"<Tag_33_a>"v33^a"</Tag_33_a>"d33,"<Tag_34_s>"v34^s"</Tag_34_s>""<Tag_34_p>"v34^p"</Tag_34_p>""<Tag_34_c>"v34^c"</Tag_34_c>""<Tag_34_i>"v34^i"</Tag_34_i>"d34,"<Tag_36_a>"v36^a"</Tag_36_a>""<Tag_36_b>"v36^b"</Tag_36_b>"d36,"<Tag_40_n>"v40^n"</Tag_40_n>""<Tag_40_x>"v40^x"</Tag_40_x>""<Tag_40_o>"v40^o"</Tag_40_o>"d40,"<Tag_41_l>"v41^l"</Tag_41_l>""<Tag_41_p>"v41^p"</Tag_41_p>"d41,"<Tag_42>"d42, if v42*0.1<>'^' then v42^* fi "</Tag_42>"d42,"<Tag_44>"d44, if v44*0.1<>'^' then v44^* fi "</Tag_44>"d44,"<Tag_45>"d45,if v45*0.1<>'^' then v45^*  fi  "</Tag_45>"d45,"<Tag_47_l>"v47^l"</Tag_47_l>""<Tag_47_e>"v47^e"</Tag_47_e>"d47,"<Tag_48>"d48,if v48*0.1<>'^' then v48^* fi "</Tag_48>"d48,"<Tag_50>"d50,if v50*0.1<>'^' then v50^* fi "</Tag_50>"d50,"<Tag_52>"d52,if v52*0.1<>'^' then v52^*  fi  "</Tag_52>"d52,"<Tag_53>"d53,if v53*0.1<>'^' then v53^* fi "</Tag_53>"d53,"<Tag_54_a>"v54^a"</Tag_54_a>""<Tag_54_b>"v54^b"</Tag_54_b>""<Tag_54_c>"v54^c"</Tag_54_c>"d54,"<Tag_55_n>"v55^n"</Tag_55_n>""<Tag_55_e>"v55^e"</Tag_55_e>""<Tag_55_g>"v55^g"</Tag_55_g>""<Tag_55_c>"v55^c"</Tag_55_c>""<Tag_55_d>"v55^d"</Tag_55_d>"d55,"<Tag_59>"d59,if v59*0.1<>'^' then v59^* fi "</Tag_59>"d59,"<Tag_62>"d62,if v62*0.1<>'^' then v62^*  fi  "</Tag_62>"d62,"<Tag_65>"d65,if v65*0.1<>'^' then v65^* fi "</Tag_65>"d65,"<Tag_75>"d75,if v75*0.1<>'^' then v75^* fi "</Tag_75>"d75,"<Tag_76>"d76 if v76*0.1<>'^' then v76^*  fi  "</Tag_76>"d76,"<Tag_77>"d77,if v77*0.1<>'^' then v77^* fi "</Tag_77>"d77,"<Tag_78>"d78, if v78*0.1<>'^' then v78^*  fi "</Tag_78>"d78,"<Tag_79>"d79, if v79*0.1<>'^' then v79^* fi "</Tag_79>"d79,"<Tag_84>"d84, if v84*0.1<>'^' then v84^* fi "</Tag_84>"d84,"<Tag_85>"d85,if v85*0.1<>'^' then v85^*  fi "</Tag_85>"d85,"<Tag_90_a>"v90^a"</Tag_90_a>""<Tag_90_b>"v90^b"</Tag_90_b>""<Tag_90_c>"v90^c"</Tag_90_c>"d90,"<Tag_92>"d92,if v92*0.1<>'^' then v92^* fi "</Tag_92>"d92,"<Tag_94>"d94,if v94*0.1<>'^' then v94^*  fi  "</Tag_94>"d94,"<Tag_96>"d96, if v96*0.1<>'^' then v96^* fi "</Tag_96>"d96,"<Tag_99>"d99, if v99*0.1<>'^' then v99^* fi "</Tag_99>"d99,"<Tag_100>"d100,if v100*0.1<>'^' then v100^* fi "</Tag_100>"d100,'</REGISTRO>'

xml2koha.map

Ver código fuente

#
# XML to MARC mapping derived from data/CAMZA.xml
#

# Some counts of Elements found in data/CAMZA.xml
# Count		Element/Tag Name
# 4		Tag_24_s
# 18		Tag_24_t
# 17		Tag_28_a
# 18		Tag_47_e
# 18		Tag_47_l
# 18		Tag_77


245 ## $b %Tag_24_s
245 ## $a %Tag_24_t
100 ## $a @Tag_28_a
260 ## $b %Tag_47_e
260 ## $a %Tag_47_l
952 ## $p %Tag_77


020 ## $a @Tag_10
020 ## $a @Tag_11
040 ## $a %Tag_76
041 ## $a @Tag_50
044 ## $a @Tag_48
080 ## $a %Tag_75_c
080 ## $b %Tag_75_l
100 ## $a @Tag_28_a
100 ## $a @Tag_28_b
100 ## $d @Tag_28_d
100 ## $c @Tag_28_o
245 ## $c @Tag_28_f
245 ## $a @Tag_24_t 
245 ## $b @Tag_24_s 
245 ## $c @Tag_24_r 
110 ## $a @Tag_29_e
110 ## $b @Tag_29_j
110 ## $c @Tag_29_l
110 ## $g @Tag_29_p
111 ## $a @Tag_40_n
111 ## $c @Tag_41_l
111 ## $d @Tag_42
111 ## $n @Tag_40_x
240 ## $a %Tag_27
250 ## $a %Tag_44
260 ## $b @Tag_47_e
260 ## $a @Tag_47_l
260 ## $c %Tag_45
300 ## $a %Tag_52_e
300 ## $b %Tag_52_i
440 ## $a @Tag_36_t
440 ## $n @Tag_36_s
440 ## $p @Tag_36_d
440 ## $v @Tag_12
440 ## $x %Tag_15
500 ## $a @Tag_59
653 ## $a @Tag_62
650 ## $a @Tag_65
900 ## $  %Tag_999 
920 ## $  %Tag_77

Artículos relacionados

Enlaces externos

 
isis_a_koha.txt · Last modified: 2009/08/18 17:09 by pabloab
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki