1 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
2 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
4 from datetime import date
6 from django.core.management.base import BaseCommand
8 from isbn.models import ISBNPool, ONIXRecord
9 from librarian import XMLNamespace
12 ONIXNS = XMLNamespace('http://ns.editeur.org/onix/3.0/reference')
15 'product_form': 'ProductForm',
16 'product_form_detail': 'ProductFormDetail',
18 'part_number': 'PartNumber',
19 'edition_type': 'EditionType',
20 'edition_number': 'EditionNumber',
21 'language': 'LanguageCode',
22 'imprint': 'ImprintName',
25 UNKNOWN = 'Autor nieznany'
28 def parse_date(date_str):
29 year = int(date_str[:4])
30 month = int(date_str[4:6])
31 day = int(date_str[6:])
32 return date(year, month, day)
35 def get_descendants(element, tags):
36 if isinstance(tags, str):
38 return element.findall('.//' + '/'.join(ONIXNS(tag) for tag in tags))
41 def get_field(element, tags, allow_multiple=False):
42 sub_elements = get_descendants(element, tags)
43 if not allow_multiple:
44 assert len(sub_elements) <= 1, 'multiple elements: %s' % tags
45 return sub_elements[0].text if sub_elements else None
48 class Command(BaseCommand):
49 help = "Import data from ONIX."
51 def add_arguments(self, parser):
52 parser.add_argument('filename')
54 def handle(self, **options):
55 filename = options['filename']
56 tree = etree.parse(open(filename))
57 for product in get_descendants(tree, 'Product'):
58 isbn = get_field(product, ['ProductIdentifier', 'IDValue'])
59 assert len(isbn) == 13
60 pool = ISBNPool.objects.get(prefix__in=[isbn[:i] for i in range(8, 11)])
62 self.parse_contributor(contributor)
63 for contributor in get_descendants(product, 'Contributor')]
66 'suffix': int(isbn[len(pool.prefix):-1]),
67 'publishing_date': parse_date(
68 get_field(product, ['PublishingDate', 'Date'], allow_multiple=True)),
69 'contributors': contributors,
71 for field, tag in DIRECT_FIELDS.items():
72 record_data[field] = get_field(product, tag) or ''
73 record = ONIXRecord.objects.create(**record_data)
74 ONIXRecord.objects.filter(pk=record.pk).update(datestamp=parse_date(product.attrib['datestamp']))
77 def parse_contributor(contributor):
79 'isni': get_field(contributor, 'IDValue'),
80 'name': get_field(contributor, 'PersonNameInverted'),
81 'corporate_name': get_field(contributor, 'CorporateName'),
82 'unnamed': get_field(contributor, 'UnnamedPersons')
85 'role': get_field(contributor, 'ContributorRole'),
87 for key, value in data.items():
89 contributor_data[key] = value
90 if contributor_data.get('name') == UNKNOWN:
91 del contributor_data['name']
92 contributor_data['unnamed'] = '01'
93 for date_elem in get_descendants(contributor, 'ContributorDate'):
94 date_role = get_field(date_elem, 'ContributorDateRole')
95 date = get_field(date_elem, 'Date')
97 contributor_data['birth_date'] = date
98 elif date_role == '51':
99 contributor_data['death_date'] = date
100 return contributor_data