class Facsimile(TeiBase): '''Extension of :class:`eulxml.xmlmap.teimap.TEI` to provide access to TEI facsimile elements''' #: local xsd schema XSD_SCHEMA = 'file://%s' % os.path.join( os.path.abspath(os.path.dirname(__file__)), 'schema', 'TEIPageView.xsd') # NOTE: using absolute path for schema to avoid path issues when # building documentation on readthedocs.org ROOT_NAME = 'TEI' xmlschema = etree.XMLSchema(etree.parse(XSD_SCHEMA)) # NOTE: not using xmlmap.loadSchema because it doesn't correctly load # referenced files in the same directory #: surface with type page, as :class:`Zone` page = xmlmap.NodeField('tei:facsimile/tei:surface[@type="page"]', Zone) #: list of pages (surface with type page) page_list = xmlmap.NodeListField('tei:facsimile/tei:surface[@type="page"]', Zone) # NOTE: tei facsimile could include illustrations, but ignoring those for now #: list of zones with type textLine or line as :class:`Zone` lines = xmlmap.NodeListField( 'tei:facsimile//tei:zone[@type="textLine" or @type="line"]', Zone) #: list of word zones (type string) as :class:`Zone` word_zones = xmlmap.NodeListField( 'tei:facsimile//tei:zone[@type="string"]', Zone) #: publication statment distributor distributor = xmlmap.StringField( 'tei:teiHeader/tei:fileDesc/tei:publicationStmt/tei:distributor') #: publication statmnt as :class:`PublicationStatement` pubstmt = xmlmap.NodeField( 'tei:teiHeader/tei:fileDesc/tei:publicationStmt', PublicationStatement) #: encoding description encoding_desc = xmlmap.NodeField('tei:teiHeader/tei:encodingDesc', xmlmap.XmlObject) #: source description for the original volume original_source = xmlmap.NodeField( 'tei:teiHeader/tei:fileDesc/tei:sourceDesc/tei:bibl[@type="original"]', Bibl) #: source description for the readux digital edition digital_source = xmlmap.NodeField( 'tei:teiHeader/tei:fileDesc/tei:sourceDesc/tei:bibl[@type="digital"]', Bibl)
class QueryTestModel(xmlmap.XmlObject): ROOT_NAMESPACES = {'ex': 'http://example.com/'} id = xmlmap.StringField('@id') name = xmlmap.StringField('name') description = xmlmap.StringField('description') wnn = xmlmap.IntegerField('wacky_node_name') sub = xmlmap.NodeField("sub", QuerySubModel) or_field = xmlmap.StringField('name|description|@id') substring = xmlmap.StringField('substring(name, 1, 1)') nsfield = xmlmap.StringField('ex:field') years = xmlmap.StringListField('year')
class OSVersionInformation(XmlObject): ROOT_NAME = 'OSVersionInformation' version = xmlmap.StringField('WindowsNTVersion') build = xmlmap.IntegerField('Build') product = xmlmap.StringField('Product') edition = xmlmap.StringField('Edition') build_info = xmlmap.StringField('BuildString') revision = xmlmap.IntegerField('Revision') flavor = xmlmap.StringField('Flavor') architecture = xmlmap.StringField('Architecture') lcid = xmlmap.IntegerField('LCID')
class Paragraph(Base): '''A single paragraph of text somewhere in a :class:`Document`.''' ROOT_NAME = 'par' align = xmlmap.StringField( '@align') # default is Left; Center, Right, Justified 'text alignment (Left, Center, Right, Justified)' left_indent = xmlmap.IntegerField('@leftIndent') 'integer left indent' right_indent = xmlmap.IntegerField('@rightIndent') 'integer right indent' start_indent = xmlmap.IntegerField('@startIndent') 'integer start indent' line_spacing = xmlmap.IntegerField('@lineSpacing') 'integer line spacing' # dropChars stuff ? lines = xmlmap.NodeListField(frns('line'), Line) 'list of :class:`Line` elements'
class Block(Base): ROOT_NAME = 'page' '''A single block of content on a :class:`Page`.''' type = xmlmap.StringField('@blockType') # Text, Table, Picture, Barcode 'type of block (Text, Table, Picture, Barcode)' left = xmlmap.IntegerField('@l') 'integer left' top = xmlmap.IntegerField('@t') 'integer top' right = xmlmap.IntegerField('@r') 'integer right' bottom = xmlmap.IntegerField('@b') 'integer bottom' # must have one & only one region; # region/rect dimensions appears to be redundant... paragraphs = xmlmap.NodeListField(frns('text/par'), Paragraph) 'list of :class:`Paragraph` elements'
class TeiHeader(_TeiBase): '''xmlmap object for a TEI (Text Encoding Initiative) header''' title = xmlmap.StringField('tei:fileDesc/tei:titleStmt/tei:title') author_list = xmlmap.NodeListField( 'tei:fileDesc/tei:titleStmt/tei:author/tei:name', TeiName) editor_list = xmlmap.NodeListField( 'tei:fileDesc/tei:titleStmt/tei:editor/tei:name', TeiName) publisher = xmlmap.StringField( 'tei:fileDesc/tei:publicationStmt/tei:publisher') publication_date = xmlmap.StringField( 'tei:fileDesc/tei:publicationStmt/tei:date') availability = xmlmap.StringField( 'tei:fileDesc/tei:publicationStmt/tei:availability') source_description = xmlmap.StringField('tei:fileDesc/tei:sourceDesc') series_statement = xmlmap.StringField('tei:fileDesc/tei:seriesStmt')
class Mandate(xmlmap.XmlObject): '''A publisher's policy compliance with an open-access funding mandate from a research funder''' funder_name = xmlmap.StringField('funder/fundername') funder_acronym = xmlmap.StringField('funder/funderacronym') funder_juliet_url = xmlmap.StringField('funder/julieturl') publisher_complies = xmlmap.StringField('publishercomplies') # complies values: yes, no, unclear compliance_type = xmlmap.StringField('compliancetype') # compliance types in appendix c selected_titles = xmlmap.StringField('selectedtitles') # selected titles values: yes (or empty) def __repr__(self): return u'<%s: %s>' % (self.__class__.__name__, self.funder_name)
class TitleInfo(Common): ROOT_NAME = 'titleInfo' title = xmlmap.StringField('mods:title') subtitle = xmlmap.StringField('mods:subTitle') part_number = xmlmap.StringField('mods:partNumber') part_name = xmlmap.StringField('mods:partName') non_sort = xmlmap.StringField('mods:nonSort') type = xmlmap.SchemaField('@type', 'titleInfoTypeAttributeDefinition') label = xmlmap.StringField('@displayLabel') def is_empty(self): '''Returns True if all titleInfo subfields are not set or empty; returns False if any of the fields are not empty.''' return not bool(self.title or self.subtitle or self.part_number \ or self.part_name or self.non_sort or self.type)
class Report(LoaderMixin, XmlObject): """ Windows Error Report """ ROOT_NAME = 'WERREPORT' XSD_SCHEMA = path.join(path.dirname(__file__), 'ms-cer2.xsd') machine = xmlmap.NodeField('MACHINEINFO', MachineInfo) """ Machine informations :type :class:`wer.schema.MachineInfo` """ user = xmlmap.StringField('USERINFO/@username') """ User informations :type :class:`wer.schema.UserInfo` """ application = xmlmap.NodeField('APPLICATIONINFO', ApplicationInfo, required=False) """ Application informations :type :class:`wer.schema.ApplicationInfo` """ event = xmlmap.NodeField('EVENTINFO', EventInfo) """ Event informations :type :class:`wer.schema.EventInfo` """ parameters = xmlmap.NodeListField('SIGNATURE/PARAMETER', Parameter) """ Event parameters :type list of :class:`wer.schema.Parameter` """ secondary_parameters = xmlmap.NodeListField('SIGNATURE/SECONDARYPARAMETER', SecondaryParameter) """ Event secondary parameters :type list of :class:`wer.schema.SecondaryParameter` """ files = xmlmap.NodeListField('FILES/FILE', File) """ Event attached files :type list of :class:`wer.schema.File` """ @property def id(self): """ Computes the signature of the record, a SHA-512 of significant values :return: SHa-512 Hex string """ h = hashlib.new('sha512') for value in (self.machine.name, self.machine.os, self.user, self.application.name, self.application.path, self.event.report_type, self.event.type, self.event.time.isoformat()): h.update(str(value).encode('utf-8')) for parameter in sorted(self.parameters, key=lambda k: getattr(k, 'id')): h.update(parameter.value.encode('utf-8')) return h.hexdigest()
class TeiDiv(_TeiBase): id = xmlmap.StringField('@xml:id') type = xmlmap.StringField('@type') author = xmlmap.StringField('tei:docAuthor/tei:name/tei:choice/tei:sic') docauthor = xmlmap.StringField('tei:docAuthor') title = xmlmap.StringField('tei:head[1]') # easy access to FIRST head title_list = xmlmap.StringListField( 'tei:head') # access to all heads when there are multiple text = xmlmap.StringField( '.' ) # short-hand mapping for full text of a div (e.g., for short divs) linegroup = xmlmap.NodeListField('tei:lg', TeiLineGroup) div = xmlmap.NodeListField('tei:div', 'self') byline = xmlmap.StringField('tei:byline') epigraph = xmlmap.NodeListField('tei:epigraph', TeiEpigraph) p = xmlmap.StringListField('tei:p') q = xmlmap.StringListField('tei:q') quote = xmlmap.StringListField('tei:quote') floatingText = xmlmap.NodeListField('tei:floatingText/tei:body/tei:div', 'self')
class Date(Common): ''':class:`~eulxml.xmlmap.XmlObject` for MODS date element (common fields for the dates under mods:originInfo).''' # this class not meant for direct use; should be extended for specific dates. date = xmlmap.StringField('text()') key_date = xmlmap.SimpleBooleanField('@keyDate', 'yes', false=None) encoding = xmlmap.SchemaField('@encoding', 'dateEncodingAttributeDefinition') point = xmlmap.SchemaField('@point', 'datePointAttributeDefinition') qualifier = xmlmap.SchemaField('@qualifier', 'dateQualifierAttributeDefinition') def is_empty(self): '''Returns False if no date value is set; returns True if any date value is set. Attributes are ignored for determining whether or not the date should be considered empty, as they are only meaningful in reference to a date value.''' return not self.node.text def __str__(self): return self.date
class PremisRelationship(premis.BasePremis): ROOT_NAME = 'relationship' type = xmlmap.StringField('p:relationshipType') subtype = xmlmap.StringField('p:relationshipSubType') #: related object identifier type related_object_type = xmlmap.StringField( 'p:relatedObjectIdentification/p:relatedObjectIdentifierType') #: related object identifier value related_object_id = xmlmap.StringField( 'p:relatedObjectIdentification/p:relatedObjectIdentifierValue') #: related event identifier type related_event_type = xmlmap.StringField( 'p:relatedEventIdentification/p:relatedEventIdentifierType') #: related event identifier value related_event_id = xmlmap.StringField( 'p:relatedEventIdentification/p:relatedEventIdentifierValue')
class UnitTitle(_EadBase): ROOT_NAME = 'unittitle' unitdate = xmlmap.NodeField("e:unitdate", DateField) "unit date" text = xmlmap.StringField('text()') 'text in this field' @property def short(self): '''Short-form of the unit title, excluding any unit date, as an instance of :class:`~eulxml.xmlmap.eadmap.UnitTitle` . Can be used with formatting anywhere the full form of the unittitle can be used.''' # if there is no unitdate to remove, just return the current object if not self.unitdate: return self # preserve any child elements (e.g., title or emph) # initialize a unittitle with a *copy* of the current node ut = UnitTitle(node=deepcopy(self.node)) # remove the unitdate node and return ut.node.remove(ut.unitdate.node) return ut
class Premis(PremisRoot): '''Preliminary :class:`~eulxml.xmlmap.XmlObject` for a PREMIS container element that can contain any of the other top-level PREMIS elements. Curently only includes mappings for a single object and list of events. ''' ROOT_NAME = 'premis' version = xmlmap.StringField('@version') '''Version of PREMIS in use; by default, new instances of :class:`Premis` will be initialized with a version of 2.1''' object = xmlmap.NodeField('p:object', Object) 'a single PREMIS :class:`object`' events = xmlmap.NodeListField('p:event', Event) 'list of PREMIS events, as instances of :class:`Event`' def __init__(self, *args, **kwargs): # version is required for schema-validity; don't override a # user-supplied version, but otherwise default to 2.1 if 'version' not in kwargs: kwargs['version'] = '2.1' super(Premis, self).__init__(*args, **kwargs)
class Note(TeiBase): 'Tei Note, used here to contain an annotation' ROOT_NAME = 'note' #: xml id id = xmlmap.StringField('@xml:id') #: responsibility resp = xmlmap.StringField('@resp') #: target target = xmlmap.StringField('@target') #: type type = xmlmap.StringField('@type') #: ana attribute, e.g. for tag identifiers ana = xmlmap.StringField('@ana') #: xlink href href = xmlmap.StringField('@xlink:href') #: list of paragraphs as strings paragraphs = xmlmap.StringListField('tei:p') #: code for the markdown used in the original annotation markdown = xmlmap.StringField('tei:code[@lang="markdown"]') #: links to related pages related_pages = xmlmap.NodeListField('tei:ref[@type="related page"]', Ref) #: list of bibliographic citations/works cited citations = xmlmap.NodeListField('tei:listBibl/tei:biblStruct', BiblStruct) # in-text citation generated from markdown; these fields # are mapped so they can be removed from the annotated tei document works_cited = xmlmap.NodeField('tei:head[text() = "Works Cited"]', xmlmap.XmlObject) zotero_items = xmlmap.NodeField( 'tei:list[contains(tei:item/tei:anchor/@xml:id, "zotero")]', xmlmap.XmlObject) works_cited_milestone = xmlmap.NodeField( 'tei:milestone[following-sibling::tei:head/text() = "Works Cited"]', xmlmap.XmlObject) # mapped to remove empty list bibl element list_bibl = xmlmap.NodeField('tei:listBibl', xmlmap.XmlObject)
class AuditTrailRecord(_FedoraBase): ''':class:`~eulxml.xmlmap.XmlObject` for a single audit entry in an :class:`AuditTrail`. ''' ROOT_NAME = 'record' ROOT_NS = FEDORA_AUDIT_NS id = xmlmap.StringField('@ID') 'id for this audit trail record' process_type = xmlmap.StringField('audit:process/@type') 'type of modification, e.g. `Fedora API-M`' action = xmlmap.StringField('audit:action') 'the particular action taken, e.g. `addDatastream`' component = xmlmap.StringField('audit:componentID') 'the component that was modified, e.g. a datastream ID such as `DC` or `RELS-EXT`' user = xmlmap.StringField('audit:responsibility') 'the user or account responsible for the change (e.g., `fedoraAdmin`)' date = FedoraDateField('audit:date') 'date the change was made, as :class:`datetime.datetime`' message = xmlmap.StringField('audit:justification') 'justification for the change, if any (i.e., log message passed to save method)'
class Item(xmlmap.XmlObject): ''':class:`~eulxml.xmlmap.XmlObject` to read Item information returned by the DigWF API. (Not all fields provided by DigWF are mapped here; only those currently in use.) ''' pid = xmlmap.StringField('@pid') 'pid (noid portion of the ARK or Fedora pid)' item_id = xmlmap.StringField('@id') 'item_id within the DigWF' control_key = xmlmap.StringField('@control_key') 'control key (e.g., ocm or ocn number in euclid; unique per book, not per volume)' display_image_path = xmlmap.StringField('display_images_path') # do we need display images count ? 'display image path' ocr_file_path = xmlmap.StringField('ocr_files_path') 'path to OCR files (text & word position)' pdf = xmlmap.StringField('pdf_file') 'path to PDF file'
class RepositoryDescription(_FedoraBase): """:class:`~eulxml.xmlmap.XmlObject` for a repository description as returned by :meth:`API_A_LITE.describeRepository` """ # default namespace is fedora access name = xmlmap.StringField('a:repositoryName') "repository name" base_url = xmlmap.StringField('a:repositoryBaseURL') "base url" version = xmlmap.StringField('a:repositoryVersion') "version of Fedora being run" pid_info = xmlmap.NodeField('a:repositoryPID', RepositoryDescriptionPid) ":class:`RepositoryDescriptionPid` - configuration info for pids" oai_info = xmlmap.NodeField('a:repositoryPID', RepositoryDescriptionOAI) ":class:`RepositoryDescriptionOAI` - configuration info for OAI" search_url = xmlmap.StringField('a:sampleSearch-URL') "sample search url" access_url = xmlmap.StringField('a:sampleAccess-URL') "sample access url" oai_url = xmlmap.StringField('a:sampleOAI-URL') "sample OAI url" admin_email = xmlmap.StringListField("a:adminEmail") "administrator emails"
class PremisObjectFormat(premis.BasePremis): ROOT_NAME = 'format' name = xmlmap.StringField('p:formatDesignation/p:formatName') version = xmlmap.StringField('p:formatDesignation/p:formatVersion')
class PremisFixity(premis.BasePremis): ROOT_NAME = 'fixity' algorithm = xmlmap.StringField('p:messageDigestAlgorithm') digest = xmlmap.StringField('p:messageDigest')
class FoxmlContentDigest(_FedoraBase): 'Content digest, as stored in full foxml (e.g. object export)' #: digest type, e.g. MD5 type = xmlmap.StringField('@TYPE') #: digest value digest = xmlmap.StringField('@DIGEST')
class DsTypeModel(xmlmap.XmlObject): ROOT_NAMESPACES = DS_NAMESPACES id = xmlmap.StringField('@ID') mimetype = xmlmap.StringField('ds:form/@MIME') format_uri = xmlmap.StringField('ds:form/@FORMAT_URI')
class DublinCoreElement(_BaseDublinCore): 'Generic Dublin Core element with access to element name and value' name = xmlmap.StringField('local-name(.)') value = xmlmap.StringField('.')
class PremisCreatingApplication(premis.BasePremis): ROOT_NAME = 'creatingApplication' name = xmlmap.StringField('p:creatingApplicationName') version = xmlmap.StringField('p:creatingApplicationVersion') date = xmlmap.DateField('p:dateCreatedByApplication')
class PremisSoftwareEnvironment(premis.BasePremis): ROOT_NAME = 'software' name = xmlmap.StringField( 'p:swName', help_text='Name of the software in original environment') version = xmlmap.StringField('p:swVersion', help_text='Software version') type = xmlmap.StringField('p:swType', help_text='Type of software')
class FindingAid(XmlModel, EncodedArchivalDescription): """ This is an :class:`~eulexistdb.models.XmlModel` version of :class:`~eulxml.xmlmap.eadmap.EncodedArchivalDescription` (EAD) object, to simplify querying for EAD content in an eXist DB. """ ROOT_NAMESPACES = { 'e': EAD_NAMESPACE, } # redeclaring namespace from eulxml to ensure prefix is correct for xpaths coverage = xmlmap.StringField('e:archdesc/e:did/e:unittitle/e:unitdate[@type="inclusive"]/@normal') # local repository *subarea* - e.g., MARBL, University Archives, Pitts repository = xmlmap.StringField('normalize-space(.//e:subarea)') objects = Manager('/e:ead') """:class:`eulexistdb.manager.Manager` - similar to an object manager for django db objects, used for finding and retrieving :class:`~keep.collection.models.FindingAid` objects from eXist. Configured to use */e:ead* as base search path. """ def generate_collection(self): '''Generate a :class:`CollectionObject` with fields pre-populated based on the contents of the current Finding Aid object. ''' repo = Repository() coll = repo.get_object(type=CollectionObject) # TODO: archive membership? # title - using 'short' form without unitdate, stripping any trailing whitespace & . or , # TODO/FIXME: does NOT work for unittitles with nested tags, e.g. title - see pomerantz coll.mods.content.title = unicode(self.unittitle.short).rstrip().rstrip('.,') # main entry/name - origination, if any if self.archdesc.did.origination: name_text = unicode(self.archdesc.did.origination) # determine type of name colltype = self.archdesc.did.node.xpath('''local-name(e:origination/e:persname | e:origination/e:corpname | e:origination/e:famname)''', namespaces=self.ROOT_NAMESPACES) if colltype == 'persname': name_type = 'personal' elif colltype == 'famname': name_type = 'family' # family names consistently end with a period, which can be removed name_text = name_text.rstrip('.') elif colltype == 'corpname': name_type = 'corporate' if name_type is not None: coll.mods.content.create_name() coll.mods.content.name.type = name_type authority = self.archdesc.did.node.xpath('string(e:origination/*/@source)', namespaces=self.ROOT_NAMESPACES) # lcnaf in the EAD is equivalent to naf in MODS if authority == 'lcnaf': coll.mods.content.name.authority = 'naf' coll.mods.content.name.name_parts.append(mods.NamePart(text=name_text)) # date coverage if self.coverage: date_encoding = {'encoding': 'w3cdtf'} # date range coll.mods.content.create_origin_info() if '/' in self.coverage: start, end = self.coverage.split('/') coll.mods.content.origin_info.created.append(mods.DateCreated(date=start, point='start', key_date=True, **date_encoding)) coll.mods.content.origin_info.created.append(mods.DateCreated(date=end, point='end', **date_encoding)) # single date else: coll.mods.content.origin_info.created.append(mods.DateCreated(date=self.coverage, key_date=True, **date_encoding)) # source id - numeric form of the manuscript/archive collection number coll.mods.content.source_id = self.archdesc.did.unitid.identifier # access restriction if self.archdesc.access_restriction: coll.mods.content.create_restrictions_on_access() coll.mods.content.restrictions_on_access.text = "\n".join([ unicode(c) for c in self.archdesc.access_restriction.content]) # use & reproduction if self.archdesc.use_restriction: coll.mods.content.create_use_and_reproduction() coll.mods.content.use_and_reproduction.text = "\n".join([ unicode(c) for c in self.archdesc.use_restriction.content]) # set initial mods:typeOfResource - not specified in EAD, but all # collections shoud be mixed material coll.mods.content.resource_type = 'mixed material' # EAD url - where does this go? # accessible at self.eadid.url return coll @staticmethod def find_by_unitid(id, archive_name): '''Retrieve a single Finding Aid by archive unitid and repository name. This method assumes a single Finding Aid should be found, so uses the :meth:`eulexistdb.query.QuerySet.get` method, which raises the following exceptions if anything other than a single match is found: * :class:`eulexistdb.exceptions.DoesNotExist` when no matches are found * :class:`eulexistdb.exceptions.ReturnedMultiple` if more than one match is found :param id: integer unitid to search on :param archive_name: name of the repository/subarea (numbering scheme) :returns: :class:`~keep.collection.models.FindingAid` instance ''' return FindingAid.objects.get(archdesc__did__unitid__identifier=id, repository=archive_name)
class PremisLinkingObject(premis.BasePremis): ROOT_NAME = 'linkingObjectIdentifier' id_type = xmlmap.StringField('p:linkingObjectIdentifierType') id = xmlmap.StringField('p:linkingObjectIdentifierValue') role = xmlmap.StringField('p:linkingObjectRole')
class SourceTech(_BaseSourceTech): ':class:`~eulxml.xmlmap.XmlObject` for Source Technical Metadata.' ROOT_NAME = 'sourcetech' # option lists for controlled vocabulary source tech fields form_options = ('', 'audio cassette', 'open reel tape', 'LP', 'CD', 'sound file (WAV)', 'sound file (MP3)', 'sound file (M4A)', 'sound file (AIFF)', 'microcassette', 'DAT', '78', '45 RPM', 'acetate disc', 'aluminum disc', 'glass disc', 'flexi disc', 'cardboard disc', 'phonograph cylinder', 'wire recording', 'dictabelt', 'other') 'controlled vocabulary for :class:`SourceTech.form`' housing_options = ('', 'jewel case', 'plastic container', 'paper sleeve', 'cardboard sleeve', 'cardboard box', 'other', 'none') 'controlled vocabulary for :class:`SourceTech.housing`' reel_sizes = ('3', '4', '5', '7', '10', '12', '14' ) # also Other -> empty field 'controlled vocabulary used to generate form options for :class:`SourceTech.reel_size`' reel_size_options = [(size, '%s"' % size) for size in reel_sizes] reel_size_options.append(('Other', 'Other')) reel_size_options.append(('Not Applicable', 'Not Applicable')) # add an empty value at the beginning of the list to force active selection reel_size_options.insert(0, ('', '')) sound_characteristic_options = ('', 'mono', 'stereo') 'controlled vocabulary for :class:`SourceTech.sound_characteristics`' speed_options = ( # delimited format is aspect, value, unit ('', ''), ('tape', ( ('tape|15/16|inches/sec', '15/16 ips'), ('tape|1.2|cm/sec', '1.2 cm/s'), ('tape|2.4|cm/sec', '2.4 cm/s'), ('tape|1 7/8|inches/sec', '1 7/8 ips'), ('tape|3 3/4|inches/sec', '3 3/4 ips'), ('tape|7 1/2|inches/sec', '7 1/2 ips'), ('tape|15|inches/sec', '15 ips'), ('tape|30|inches/sec', '30 ips'), ('tape|other|other', 'Other'), )), ('phono disc', ( ('phono disc|16|rpm', '16 rpm'), ('phono disc|33 1/3|rpm', '33 1/3 rpm'), ('phono disc|45|rpm', '45 rpm'), ('phono disc|78|rpm', '78 rpm'), ('phono disc|other|other', 'Other'), )), ( 'phono cylinder', ( ('phono cylinder|90|rpm', '90 rpm'), ('phono cylinder|120|rpm', '120 rpm'), ('phono cylinder|160|rpm', '160 rpm'), ('phono cylinder|other|other', 'Other'), ), ), ( 'other', (('other|other|other', 'Other'), ), ), ('na|Not applicable|na', 'Not Applicable'), ) 'controlled vocabulary for :class:`SourceTech.speed`, grouped by format' # NOTE: speed should be displayed as ips but saved to xml as inches/sec # speed options is formatted for grouped options in django select widget # planned schema location (schema not yet available) #XSD_SCHEMA = 'http://pid.emory.edu/ns/2010/sourcetech/v1/sourcetech-1.xsd' #xmlschema = xmlmap.loadSchema(XSD_SCHEMA) note = xmlmap.StringField('st:note[@type="general"]', required=False, verbose_name='General Note', help_text='General note about the physical item') 'general note' note_list = xmlmap.StringListField('st:note[@type="general"]') related_files = xmlmap.StringField( 'st:note[@type="relatedFiles"]', required=False, help_text= 'IDs of other digitized files for the same item, separated by semicolons. Required for multi-part items.' ) 'related files (string of IDs delimited by semicolons' related_files_list = xmlmap.StringListField( 'st:note[@type="relatedFiles"]') # NOTE: according to spec, related_files is required if multi-part-- # - not tracking multi-part for Min Items (that I know of) conservation_history = xmlmap.StringField( 'st:note[@type="conservationHistory"]', required=False) 'note about conservation history' conservation_history_list = xmlmap.StringListField( 'st:note[@type="conservationHistory"]') speed = xmlmap.NodeField('st:speed/st:measure[@type="speed"]', SourceTechMeasure) ':class:`SourceTechMeasure`' sublocation = xmlmap.StringField( 'st:sublocation', required=False, help_text= 'Storage location within the collection (e.g., box and folder)') 'storage location within the collection' form = xmlmap.StringField( 'st:form[@type="sound"]', choices=form_options, required=False, help_text='The physical form or medium of the resource') 'physical format - options controlled by :class:`SourceTech.form_options`' form_list = xmlmap.StringListField('st:form[@type="sound"]') sound_characteristics = xmlmap.StringField( 'st:soundChar', choices=sound_characteristic_options, required=False) 'sound characteristics - options controlled by :class:`SourceTech.sound_characteristic_options`' stock = xmlmap.StringField( 'st:stock', verbose_name='Tape Brand/Stock', help_text='The brand or stock of the magnetic tape', required=False) 'Stock or brand of source media' stock_list = xmlmap.StringListField('st:stock') housing = xmlmap.StringField( 'st:housing[@type="sound"]', choices=housing_options, required=False, help_text='Type of housing for the source item') 'Type of housing - options controlled by :class:`SourceTech.housing_options`' reel_size = xmlmap.NodeField( 'st:reelSize/st:measure[@type="diameter"][@aspect="reel size"]', SourceTechMeasure, required=False) ':class:`SourceTechMeasure`' # tech_note is migrate/view only technical_note = xmlmap.StringListField('st:note[@type="technical"]', required=False) 'note with type="technical"'
class DublinCore(_BaseDublinCore): """ XmlObject for Simple (unqualified) Dublin Core metadata. If no node is specified when initialized, a new, empty Dublin Core XmlObject will be created. """ ROOT_NAME = 'dc' XSD_SCHEMA = "http://www.openarchives.org/OAI/2.0/oai_dc.xsd" contributor = xmlmap.StringField("dc:contributor", required=False) contributor_list = xmlmap.StringListField("dc:contributor", verbose_name='Contributors') coverage = xmlmap.StringField("dc:coverage", required=False) coverage_list = xmlmap.StringListField("dc:coverage", verbose_name='Coverage') #? creator = xmlmap.StringField("dc:creator", required=False) creator_list = xmlmap.StringListField("dc:creator", verbose_name='Creators') date = xmlmap.StringField("dc:date", required=False) date_list = xmlmap.StringListField("dc:date", verbose_name='Dates') description = xmlmap.StringField("dc:description", required=False) description_list = xmlmap.StringListField("dc:description", verbose_name='Descriptions') format = xmlmap.StringField("dc:format", required=False) format_list = xmlmap.StringListField("dc:format", verbose_name='Formats') identifier = xmlmap.StringField("dc:identifier", required=False) identifier_list = xmlmap.StringListField("dc:identifier", verbose_name='Identifiers') language = xmlmap.StringField("dc:language", required=False) language_list = xmlmap.StringListField("dc:language", verbose_name='Languages') publisher = xmlmap.StringField("dc:publisher", required=False) publisher_list = xmlmap.StringListField("dc:publisher", verbose_name='Publishers') relation = xmlmap.StringField("dc:relation", required=False) relation_list = xmlmap.StringListField("dc:relation", verbose_name='Relations') rights = xmlmap.StringField("dc:rights", required=False) rights_list = xmlmap.StringListField("dc:rights", verbose_name='Rights') source = xmlmap.StringField("dc:source", required=False) source_list = xmlmap.StringListField("dc:source", verbose_name='Sources') subject = xmlmap.StringField("dc:subject", required=False) subject_list = xmlmap.StringListField("dc:subject", verbose_name='Subjects') title = xmlmap.StringField("dc:title", required=False) title_list = xmlmap.StringListField("dc:title", verbose_name='Titles') type = xmlmap.StringField("dc:type", required=False) type_list = xmlmap.StringListField("dc:type", verbose_name='Types') elements = xmlmap.NodeListField('dc:*', DublinCoreElement) 'list of all DC elements as instances of :class:`DublinCoreElement`' # RDF declaration of the Recommended DCMI types DCMI_TYPES_RDF = 'http://dublincore.org/2010/10/11/dctype.rdf' DCMI_TYPE_URI = 'http://purl.org/dc/dcmitype/' if rdflib: DCMI_TYPE_URI = rdflib.URIRef(DCMI_TYPE_URI) _dcmi_types_graph = None @property def dcmi_types_graph(self): 'DCMI Types Vocabulary as an :class:`rdflib.Graph`' # only initialize if requested; then save the result if self._dcmi_types_graph is None: self._dcmi_types_graph = rdflib.Graph() self._dcmi_types_graph.parse(self.DCMI_TYPES_RDF) return self._dcmi_types_graph _dcmi_types = None @property def dcmi_types(self): '''DCMI Type Vocabulary (recommended), as documented at http://dublincore.org/documents/dcmi-type-vocabulary/''' if self._dcmi_types is None: # generate a list of DCMI types based on the RDF dctype document self._dcmi_types = [] # get all items with rdf:type of rdfs:Clas items = self.dcmi_types_graph.subjects(rdflib.RDF.type, rdflib.RDFS.Class) for item in items: # check that this item is defined by dcmitype if (item, rdflib.RDFS.isDefinedBy, self.DCMI_TYPE_URI) in self.dcmi_types_graph: # add the label to the list self._dcmi_types.append(str(self.dcmi_types_graph.label(subject=item))) return self._dcmi_types else: # no rdflib dcmi_types_graph = None dcmi_types = None
class MetaParameter(XmlObject): id = xmlmap.IntegerField('substring(name(), 10)') value = xmlmap.StringField('text()')