def test_recordstatus(schematron_fx): """Test that RECORDSTATUS can always be 'submission', and also 'update' and 'dissemination' for CSC. """ (mets, root) = parse_xml_file('mets_valid_complete.xml') hdr = find_element(root, 'metsHdr', 'mets') set_attribute(hdr, 'RECORDSTATUS', 'mets', 'update') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 set_attribute(hdr, 'RECORDSTATUS', 'mets', 'dissemination') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 agent = find_element(hdr, 'name', 'mets') agent.text = 'CSC - IT Center for Science Ltd.' set_attribute(hdr, 'RECORDSTATUS', 'mets', 'submission') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 set_attribute(hdr, 'RECORDSTATUS', 'mets', 'update') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 set_attribute(hdr, 'RECORDSTATUS', 'mets', 'dissemination') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_mdtype_items_digiprovmd(schematron_fx, mdtype, othermdtype, mdtypeversion): """Test that all valid metadata types and their versions work properly. :schematron_fx: Schematron compile fixture :mdtype: MDTYPE attribute value :othermdtype: OTHERMDTYPE attribute valur :mdtypeversion: MDTYPEVERSION attribute value """ (mets, root) = parse_xml_file('mets_valid_complete.xml') elem_handler = find_element(root, 'digiprovMD', 'mets') elem_handler = find_element(elem_handler, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPE', 'mets', mdtype) if othermdtype is not None: set_attribute(elem_handler, 'OTHERMDTYPE', 'mets', othermdtype) # Test that all MDTYPEVERSIONs work with all specifications for specversion in [ '1.5.0', '1.6.0', '1.7.0', '1.7.1', '1.7.2', '1.7.3', '1.7.4' ]: if specversion in ['1.7.0', '1.7.1', '1.7.2', '1.7.3', '1.7.4']: fix_version_17(root) else: set_attribute(root, 'CATALOG', 'fikdk', specversion) set_attribute(root, 'SPECIFICATION', 'fikdk', specversion) for version in mdtypeversion: set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', version) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Test unknown version fix_version_17(root) set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_addml_reference_version(schematron_fx): """Test element 'reference' with ADDML versions 8.2 and 8.3. It is required only in 8.2. :schematron_fx: Schematron compile fixture """ xml = METS_HEAD+'''<addml:addml><addml:dataset/></addml:addml>'''+METS_TAIL # Element 'reference' is required in 8.2, but missing (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FIRED) == 1 assert svrl.count(SVRL_FAILED) == 1 # Element 'reference' is required in 8.2, and it exists elem_handler = find_element(root, 'dataset', 'addml') set_element(elem_handler, 'reference', 'addml') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # No checks with version 8.3 elem_handler = find_element(root, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', '8.3') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets, params=False) assert svrl.count(SVRL_FIRED) == 0 assert svrl.count(SVRL_FAILED) == 0
def test_mdtype_items_mdwrap(schematron_fx, context, mdtype, othermdtype, mdtypeversion): """Test that all valid metadata types and their versions work properly. :schematron_fx: Schematron compile fixture :context: METS section to be tested :mdtype: MDTYPE attribute value :othermdtype: OTHERMDTYPE attribute valur :mdtypeversion: MDTYPEVERSION attribute value """ (mets, root) = parse_xml_file('mets_valid_complete.xml') fix_version_17(root) elem_handler = find_element(root, context, 'mets') elem_handler = find_element(elem_handler, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPE', 'mets', mdtype) if othermdtype is not None: set_attribute(elem_handler, 'OTHERMDTYPE', 'mets', othermdtype) # Test that unknown OTHERMDTYPE gives error, if MDTYPE is not 'OTHER' set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', mdtypeversion[0]) set_attribute(elem_handler, 'OTHERMDTYPE', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) if mdtype == 'OTHER': assert svrl.count(SVRL_FAILED) == 0 else: assert svrl.count(SVRL_FAILED) == 1
def test_disallowed_attribute_premis_digiprov(schematron_fx, premisroot, mdtype): """Test that attributes 'authority', 'authorityURI', 'valueURI' in PREMIS 2.3 are disallowed in PREMIS 2.2. :schematron_fx: Schematron compile fixture :premisroot: Root element in PREMIS. :mdtype: MDTYPE value """ xml = '''<mets:digiprovMD xmlns:mets="%(mets)s"> <mets:mdWrap MDTYPEVERSION="2.3"><mets:xmlData/></mets:mdWrap> </mets:digiprovMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_wrap = find_element(root, 'mdWrap', 'mets') set_attribute(elem_wrap, 'MDTYPE', 'mets', mdtype) elem_handler = find_element(elem_wrap, 'xmlData', 'mets') elem_handler = set_element(elem_handler, premisroot, 'premis') elem_handler = set_element(elem_handler, 'xxx', 'premis') for disallowed in ['authority', 'authorityURI', 'valueURI']: set_attribute(elem_handler, disallowed, 'premis', 'default') # Works in 2.3 svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Disallowed in 2.2 set_attribute(elem_wrap, 'MDTYPEVERSION', 'mets', '2.2') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 3 # 2.2 works, if attributes removed elem_handler.clear() svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_identifier_value_premis_event_agent(schematron_fx, premisroot, mdtype, nonempty): """PREMIS identifier elements can not be empty. Test that a value in the element is required. :schematron_fx: Schematron compile fixture :premisroot: PREMIS root element name :mdtype: MDTYPE :nonempty: element that requires a value """ xml = '''<mets:digiprovMD xmlns:mets="%(mets)s"> <mets:mdWrap MDTYPEVERSION="2.3"><mets:xmlData/></mets:mdWrap> </mets:digiprovMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_handler = find_element(root, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPE', 'mets', mdtype) elem_handler = find_element(elem_handler, 'xmlData', 'mets') for elem in premisroot: elem_handler = set_element(elem_handler, elem, 'premis') elem_handler = set_element(elem_handler, nonempty, 'premis') # Empty identifier element fails svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # Arbitrary value added elem_handler.text = 'xxx' svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_palette_profile(schematron_fx): """Palette color profile test. Palettte requires Colormap. :schematron_fx: Schematron compile fixture """ (mix, root) = parse_xml_file('mix_valid_minimal.xml') elem_handler = find_element(root, 'colorSpace', 'mix') elem_handler.text = 'PaletteColor' elem_handler = find_element(root, 'samplesPerPixel', 'mix') elem_handler.text = '1' # Colormap missing svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mix) assert svrl.count(SVRL_FAILED) == 1 # Colormap exists, but it requires a reference elem_handler = find_element(root, 'ImageColorEncoding', 'mix') elem_handler = set_element(elem_handler, 'Colormap', 'mix') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mix) assert svrl.count(SVRL_FAILED) == 1 # Reference added set_element(elem_handler, 'colormapReference', 'mix') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mix) assert svrl.count(SVRL_FAILED) == 0
def make_colorsample(colorspace, sample, addsample, extrasample): """ Modifies MIX metadata with given colorspace and sample info. :colorspace: Colorspace to be tested :sample: Number of samples required by the colorspace :addsample: Offset for the required sample :extraSample: Boolean, true if extra sample is defined. :returns: Modified MIX XML tree """ # Prepare the MIX data for the colorspace and sample test (mix, root) = parse_xml_file('mix_valid_minimal.xml') make_colorprofile(root) elem_handler = find_element(root, 'ImageColorEncoding', 'mix') xml = '''<mix:Colormap xmlns:mix="%(mix)s"> <mix:colormapReference/></mix:Colormap>''' % NAMESPACES elem_handler.append(ET.XML(xml)) elem_handler = find_element(root, 'colorSpace', 'mix') elem_handler.text = colorspace elem_handler = find_element(root, 'samplesPerPixel', 'mix') elem_handler.text = str(sample + addsample) elem_handler = find_element(root, 'ImageColorEncoding', 'mix') elem_extra = find_element(elem_handler, 'extraSamples', 'mix') if elem_extra is not None: elem_handler.remove(elem_extra) if extrasample: extra = '{%(mix)s}extraSamples' % NAMESPACES elem_handler.insert(2, ET.Element(extra)) return mix
def test_mdtype_items_rightsmd(schematron_fx): """Test that all valid metadata types and their versions work properly. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') elem_handler = find_element(root, 'rightsMD', 'mets') elem_handler = find_element(elem_handler, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPE', 'mets', 'PREMIS:RIGHTS') # Test that all MDTYPEVERSIONs work with all specifications for specversion in [ '1.5.0', '1.6.0', '1.7.0', '1.7.1', '1.7.2', '1.7.3', '1.7.4' ]: if specversion in ['1.7.0', '1.7.1', '1.7.3', '1.7.4']: fix_version_17(root) else: set_attribute(root, 'CATALOG', 'fikdk', specversion) set_attribute(root, 'SPECIFICATION', 'fikdk', specversion) for version in ['2.3', '2.2']: set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', version) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Test unknown version fix_version_17(root) set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_disallowed_attribute_premis_rightsmd(schematron_fx): """Test that attributes 'authority', 'authorityURI', 'valueURI' in PREMIS 2.3 are disallowed in PREMIS 2.2. :schematron_fx: Schematron compile fixture """ xml = '''<mets:rightsMD xmlns:mets="%(mets)s" xmlns:premis="%(premis)s"> <mets:mdWrap MDTYPE="PREMIS:RIGHTS" MDTYPEVERSION="2.3"> <mets:xmlData><premis:rights><premis:rightsStatement/> </premis:rights></mets:xmlData></mets:mdWrap> </mets:rightsMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_handler = find_element(root, 'rightsStatement', 'premis') elem_handler = set_element(elem_handler, 'xxx', 'premis') for disallowed in ['authority', 'authorityURI', 'valueURI']: set_attribute(elem_handler, disallowed, 'premis', 'default') # Works in 2.3 svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Disallowed in 2.2 elem_wrap = find_element(root, 'mdWrap', 'mets') set_attribute(elem_wrap, 'MDTYPEVERSION', 'mets', '2.2') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 3 # 2.2 works, if attributes removed elem_handler.clear() svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_pronom_codes(schematron_fx, fileformat, pronom): """Test that checks for PRONOM code matching to MIME type is done. :schematron_fx: Schematron compile fixture :fileformat: File format as MIME type :pronom: Allowed PRONOM codes for the file format """ xml = '''<mets:techMD xmlns:mets="%(mets)s" xmlns:premis="%(premis)s"> <mets:mdWrap MDTYPEVERSION="2.3"><mets:xmlData><premis:object> <premis:objectCharacteristics> <premis:format><premis:formatDesignation><premis:formatName/> </premis:formatDesignation><premis:formatRegistry> <premis:formatRegistryKey/></premis:formatRegistry> </premis:format></premis:objectCharacteristics> </premis:object></mets:xmlData></mets:mdWrap> </mets:techMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_handler = find_element(root, 'formatName', 'premis') elem_handler.text = fileformat elem_handler = find_element(root, 'formatRegistryKey', 'premis') # All acceptable PRONOM codes work for pronomcode in pronom: elem_handler.text = pronomcode svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Arbitrary PRONOM code fails elem_handler.text = 'xxx' svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_othermdtype(schematron_fx, context): """Test that OTHERMDTYPE and the version are mandatory, but can be anything in all METS sections, if MDTYPE is OTHER. :schematron_fx: Schematron compile fixture :context: METS section to be tested """ (mets, root) = parse_xml_file('mets_valid_complete.xml') # OTHERMDTYPE and version can be anything elem_handler = find_element(root, context, 'mets') elem_handler = find_element(elem_handler, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPE', 'mets', 'OTHER') set_attribute(elem_handler, 'OTHERMDTYPE', 'mets', 'xxx') set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Version is mandatory del_attribute(elem_handler, 'MDTYPEVERSION', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # OTHERMDTYPE is missing del_attribute(elem_handler, 'OTHERMDTYPE', 'mets') set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 2
def test_rightsstatement_failure(schematron_fx): """There was an accidential error in specification 1.5.0 where rightsStatement was accepted as root element in PREMIS:RIGHTS. The correct element is 'rights'. Test that 'rights' works in all versions, and 'rightsStatement' gives a warning with specification 1.5.0 and error in all other versions. :schematron_fx: Schematron compile fixture """ xml = '''<mets:mets fi:CATALOG="1.6.0" xmlns:mets="%(mets)s" xmlns:dc="%(dc)s" xmlns:premis="%(premis)s" xmlns:fi="%(fikdk)s"> <mets:dmdSec><mets:mdWrap MDTYPE="DC" MDTYPEVERSION="1.1"> <mets:xmlData><dc:subject/></mets:xmlData></mets:mdWrap> </mets:dmdSec> <mets:amdSec> <mets:techMD> <mets:mdWrap MDTYPE='PREMIS:OBJECT' MDTYPEVERSION="2.3"> <mets:xmlData><premis:object/></mets:xmlData></mets:mdWrap> </mets:techMD> <mets:rightsMD> <mets:mdWrap MDTYPE="PREMIS:RIGHTS" MDTYPEVERSION="2.3"> <mets:xmlData><premis:rightsStatement/> </mets:xmlData></mets:mdWrap></mets:rightsMD> <mets:digiprovMD> <mets:mdWrap MDTYPE='PREMIS:EVENT' MDTYPEVERSION="2.3"> <mets:xmlData><premis:event/></mets:xmlData></mets:mdWrap> </mets:digiprovMD></mets:amdSec></mets:mets>''' % NAMESPACES (mets, root) = parse_xml_string(xml) # rightsStatement gives an error with specification 1.6.0 svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # rightsStatement works with specification 1.5.0 set_attribute(root, 'CATALOG', 'fikdk', '1.5.0') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # rights works with specification 1.6.0 set_attribute(root, 'CATALOG', 'fikdk', '1.6.0') elem_handler = find_element(root, 'mdWrap[@MDTYPE="PREMIS:RIGHTS"]', 'mets') elem_handler = find_element(elem_handler, 'xmlData', 'mets') elem_handler.clear() set_element(elem_handler, 'rights', 'premis') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # rights works with specification 1.5.0 set_attribute(root, 'CATALOG', 'fikdk', '1.5.0') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_value_items_root(schematron_fx, attribute, nspace, fixed): """Test that a value is required in a certain attributes. :schematron_fx: Schematron compile fixture :attribute: Attribute, where the value is required :nspace: Namespace key of the attribute :fixed: Boolean, if the required value is fixed """ (mets, root) = parse_xml_file('mets_valid_complete.xml') if nspace == 'fi': fix_version_17(root) # Use arbitrary value elem_handler = find_element(root, 'mets', 'mets') set_attribute(elem_handler, attribute, nspace, 'aaa') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) if fixed: assert svrl.count(SVRL_FAILED) == 1 else: assert svrl.count(SVRL_FAILED) == 0 # Use empty value set_attribute(elem_handler, attribute, nspace, '') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_addml_headerlevel_version(schematron_fx): """Test element 'headerLevel' with ADDML versions 8.2 and 8.3. It is a new element in 8.3 (forbidden in 8.2). :schematron_fx: Schematron compile fixture """ xml = '''<addml:addml><addml:dataset><addml:reference/><addml:flatFiles> <addml:flatFileDefinitions><addml:flatFileDefinition> <addml:recordDefinitions><addml:recordDefinition> <addml:headerLevel/> </addml:recordDefinition></addml:recordDefinitions> </addml:flatFileDefinition></addml:flatFileDefinitions> </addml:flatFiles></addml:dataset></addml:addml>''' \ % NAMESPACES (mets, root) = parse_xml_string(METS_HEAD+xml+METS_TAIL) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') # Element 'headerLevel' is forbidden in 8.2 svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets, params=False) assert svrl.count(SVRL_FIRED) == 2 assert svrl.count(SVRL_FAILED) == 1 # No checks with version 8.3 elem_handler = find_element(root, 'mdWrap', 'mets') set_attribute(elem_handler, 'MDTYPEVERSION', 'mets', '8.3') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets, params=False) assert svrl.count(SVRL_FIRED) == 0 assert svrl.count(SVRL_FAILED) == 0
def test_mix_optional_element_rules(schematron_fx, elementkey, subelements, condition, newfired): """Test for checks to elements that become mandatory when optional element has been used and optionally some condition in true. :schematron_fx: Schematron compile fixture :elementkey: Optional element :subelements: Subelement :condition: Element and value that is needed to make subelements mandatory If None, the subelement becomes mandatory with elementkey :newfired: Such errors that are expected to be generated, which are irrelevant in this test """ (mix, root) = parse_xml_file('mix_valid_minimal.xml') found = root for iter_elem in elementkey: elem_handler = find_element(root, iter_elem, 'mix') if elem_handler is None: found = set_element(found, iter_elem, 'mix') else: found = elem_handler elem_handler = found if condition is not None: elem_condition = set_element(elem_handler, condition[0], 'mix') if condition[1] is not None: elem_condition.text = condition[1] svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mix) assert svrl.count(SVRL_FAILED) == len(subelements) + newfired[0] for subelement in subelements: set_element(elem_handler, subelement, 'mix') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mix) assert svrl.count(SVRL_FAILED) == newfired[1]
def test_objid_unique(schematron_fx): """Check that error is given, if OBJID is not unique with METS IDs, except for CONTENTID that can be identical to OBJID. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') objid = get_attribute(root, 'OBJID', 'mets') contentid = get_attribute(root, 'CONTENTID', 'fikdk') set_attribute(root, 'CONTENTID', 'fikdk', objid) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 set_attribute(root, 'CONTENTID', 'fikdk', contentid) elem_handler = find_element(root, 'dmdSec', 'mets') section_id = get_attribute(elem_handler, 'ID', 'mets') set_attribute(root, 'OBJID', 'mets', section_id) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 set_attribute(root, 'OBJID', 'mets', objid) fix_version_17(root) set_attribute(root, 'CONTRACTID', 'fi', objid) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_mandatory_elements( schematron_fx, testset, namespace, filename, schfile): """Test mandatory element checks for metadata. Here we practically give a minimal XML, which is valid in a certain namespace. Then we start to remove elements from it one by one (until nothing remains). With every loop the number of fired schematron rules and failures are different. Since the next loop is dependent on the previous loop, the whole looping is done inside one test run. :schematron_fx: Schematron compile fixture :testset: A list of tuples containing the element to be removed, number of expected schematron checks, and number of expected failures. :namespace: Namespace key, where the test is done. :filename: File name containing the valid minimal METS :schfile: Schematron file to use in the test """ (mets, root) = parse_xml_file(filename) for testcase in testset: (leafelement, fired, failed) = testcase if leafelement is not None: elem_handler = find_element(root, leafelement, namespace) elem_handler.clear() svrl = schematron_fx(schematronfile=schfile, xmltree=mets, params=False) assert svrl.count(SVRL_FIRED) == fired assert svrl.count(SVRL_FAILED) == failed svrl = schematron_fx(schematronfile=schfile, xmltree=mets) assert svrl.count(SVRL_FAILED) == failed
def test_identifier_value_object(schematron_fx, nonempty): """PREMIS identifier elements can not be empty. Test that a value in the element is required. :schematron_fx: Schematron compile fixture :nonempty: element that requires a value """ xml = '''<mets:techMD xmlns:mets="%(mets)s" xmlns:premis="%(premis)s"> <mets:mdWrap MDTYPE="PREMIS:OBJECT" MDTYPEVERSION="2.3"> <mets:xmlData><premis:object><premis:objectIdentifier/> </premis:object></mets:xmlData></mets:mdWrap> </mets:techMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_handler = find_element(root, 'objectIdentifier', 'premis') elem_handler = set_element(elem_handler, nonempty, 'premis') # Empty identifier element fails svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # Arbitrary value added elem_handler.text = 'xxx' svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0
def test_checksums(schematron_fx, algorithm): """Test that the controlled vocabulary for messageDigestAlgorithm work. :schematron_fx: Schematron compile fixture :algorithm: Valid algorithm name or 'xxx' as invalid arbitrary name. """ xml = '''<mets:techMD xmlns:mets="%(mets)s" xmlns:premis="%(premis)s" xmlns:xsi="%(xsi)s"> <mets:mdWrap MDTYPE="PREMIS:OBJECT" MDTYPEVERSION="2.3"> <mets:xmlData> <premis:object xsi:type="premis:file"> <premis:objectCharacteristics><premis:fixity> <premis:messageDigestAlgorithm/> </premis:fixity></premis:objectCharacteristics> </premis:object> </mets:xmlData> </mets:mdWrap> </mets:techMD>''' % NAMESPACES (mets, root) = parse_xml_string(xml) (mets, root) = add_containers(root, 'mets:mets/mets:amdSec') elem_handler = find_element(root, 'messageDigestAlgorithm', 'premis') elem_handler.text = algorithm svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) if algorithm == 'xxx': assert svrl.count(SVRL_FAILED) == 2 else: assert svrl.count(SVRL_FAILED) == 1
def test_dependent_attributes_structmap(schematron_fx, nspace): """Test attribute dependencies with another attribute. Some attributes become mandatory or disallowed, if another attribute is used. :schematron_fx: Schematron compile fixture :nspace: Namespace key of the attributes """ (mets, root) = parse_xml_file('mets_valid_complete.xml') elem_handler = find_element(root, 'structMap', 'mets') if nspace == 'fi': fix_version_17(root) # Both attributes set_attribute(elem_handler, 'PID', nspace, 'xxx') set_attribute(elem_handler, 'PIDTYPE', nspace, 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Just the second attribute del_attribute(elem_handler, 'PID', nspace) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # No attributes del_attribute(elem_handler, 'PIDTYPE', nspace) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Just the first attribute set_attribute(elem_handler, 'PID', nspace, 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_fileid(schematron_fx): """Test that FILEID is allowed in fptr or area, but disallowed, if missing. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') # FILEID in fptr and area elem_handler = find_element(root, 'fptr', 'mets') elem_handler_area = set_element(elem_handler, 'area', 'mets') set_attribute(elem_handler_area, 'FILEID', 'mets', get_attribute(elem_handler, 'FILEID', 'mets')) svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # FILEID only in area del_attribute(elem_handler, 'FILEID', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Also area missing del_element(elem_handler, 'area', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_dependent_attributes_mdwrap(schematron_fx): """Test attribute dependencies with another attribute. Some attributes become mandatory or disallowed, if another attribute is used. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') elem_handler = find_element(root, 'mdWrap', 'mets') # Both attributes set_attribute(elem_handler, 'CHECKSUM', 'mets', 'xxx') set_attribute(elem_handler, 'CHECKSUMTYPE', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Just the second attribute del_attribute(elem_handler, 'CHECKSUM', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 # No attributes del_attribute(elem_handler, 'CHECKSUMTYPE', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Just the first attribute set_attribute(elem_handler, 'CHECKSUM', 'mets', 'xxx') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def prepare_xml(context_element, version): """The EAD3 metadata is prepared here for all the tests below. :context_element: Context element, where the test is done :version: EAD3 version to be used. """ xml = '''<mets:dmdSec xmlns:mets="%(mets)s" xmlns:ead3="%(ead3)s"> <mets:mdWrap MDTYPE="EAD3" MDTYPEVERSION="1.1.0"> <mets:xmlData><ead3:ead/></mets:xmlData></mets:mdWrap> </mets:dmdSec>''' % NAMESPACES (ead3, root) = parse_xml_string(xml) (ead3, root) = add_containers(root, 'mets:mets') elem_handler = find_element(root, 'ead', 'ead3') if context_element is not None: elem_context = set_element(elem_handler, context_element, 'ead3') elem_version = find_element(root, 'mdWrap', 'mets') set_attribute(elem_version, 'MDTYPEVERSION', 'mets', version) return (ead3, elem_context, elem_version)
def make_colorprofile(root): """Add color profile to MIX XML tree :root: XML tree root element """ elem_handler = find_element(root, 'PhotometricInterpretation', 'mix') xml = '''<mix:ColorProfile xmlns:mix="%(mix)s"> <mix:IccProfile><mix:iccProfileName/></mix:IccProfile> </mix:ColorProfile>''' % NAMESPACES elem_handler.append(ET.XML(xml))
def test_section_schemas(catalog_fx, rootelement, namespace, section): """Test that section schemas in the catalog work in validation. :catalog_fx: Schema catalog validation fixture :rootelement: Root element of the section metadata :namespace: Namespace of the section metadata :section: METS metadata section """ (mets, root) = prepare_xml_for_tests() elem_handler = find_element(root, section, 'mets') elem_handler = find_element(elem_handler, 'xmlData', 'mets') elem_handler.clear() elem_handler = set_element(elem_handler, rootelement, namespace) if rootelement == 'object': set_attribute(elem_handler, 'type', 'xsi', 'premis:file') set_element(elem_handler, 'xxx', namespace) (returncode, _, stderr) = catalog_fx(xmltree=mets) assert returncode == 3 assert b'xxx' in stderr
def test_digiprov_object(schematron_fx): """PREMIS:OBJECT is allowed in digiprovMD, if it's type is representation. :schematron_fx: Schematron compile fixture """ xml = '''<mets:mets fi:CATALOG="1.6.0" xmlns:mets="%(mets)s" xmlns:premis="%(premis)s" xmlns:xsi="%(xsi)s" xmlns:fi="%(fikdk)s" xmlns:dc="%(dc)s"> <mets:dmdSec> <mets:mdWrap MDTYPE='DC' MDTYPEVERSION="1.1"> <mets:xmlData><dc:subject/></mets:xmlData></mets:mdWrap> </mets:dmdSec><mets:amdSec> <mets:techMD> <mets:mdWrap MDTYPE='PREMIS:OBJECT' MDTYPEVERSION="2.3"> <mets:xmlData> <premis:object/></mets:xmlData></mets:mdWrap></mets:techMD> <mets:digiprovMD> <mets:mdWrap MDTYPE='PREMIS:OBJECT' MDTYPEVERSION="2.3"> <mets:xmlData> <premis:object xsi:type='premis:representation'/> </mets:xmlData></mets:mdWrap></mets:digiprovMD> <mets:digiprovMD> <mets:mdWrap MDTYPE='PREMIS:EVENT' MDTYPEVERSION="2.3"> <mets:xmlData><premis:event/></mets:xmlData></mets:mdWrap> </mets:digiprovMD></mets:amdSec></mets:mets>''' % NAMESPACES ET.register_namespace('premis', NAMESPACES['premis']) (mets, root) = parse_xml_string(xml) # Works with premis:representation svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 0 # Fails with other values elem_handler = find_element(root, 'digiprovMD', 'mets') elem_handler = find_element(elem_handler, 'object', 'premis') set_attribute(elem_handler, 'type', 'xsi', 'premis:file') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1 set_attribute(elem_handler, 'type', 'xsi', 'premis:bitstream') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def prepare_xml(context_element, version): """The MODS metadata is prepared here for all the tests below. :context_element: Context element, where the test is done :version: MODS version to be used. """ xml = '''<mets:dmdSec xmlns:mets="%(mets)s" xmlns:mods="%(mods)s"> <mets:mdWrap MDTYPE="MODS" MDTYPEVERSION="3.7"> <mets:xmlData><mods:mods/></mets:xmlData></mets:mdWrap> </mets:dmdSec>''' % NAMESPACES (mods, root) = parse_xml_string(xml) (mods, root) = add_containers(root, 'mets:mets') elem_handler = find_element(root, 'mods', 'mods') if context_element is not None: elem_context = set_element(elem_handler, context_element, 'mods') else: elem_context = elem_handler elem_version = find_element(root, 'mdWrap', 'mets') set_attribute(elem_version, 'MDTYPEVERSION', 'mets', version) return (mods, elem_context, elem_version)
def test_disallowed_items_sourcemd(schematron_fx): """Test if use of disallowed atrtibute or element causes error. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') # Set disallowed attribute/element elem_handler = find_element(root, 'sourceMD', 'mets') set_element(elem_handler, 'mdRef', 'mets') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == 1
def test_missing_links_dmdsec(schematron_fx): """Test the case where linking missing from ADMID, DMDID and FILEID to corresponding METS sections. :schematron_fx: Schematron compile fixture """ (mets, root) = parse_xml_file('mets_valid_complete.xml') elem_handler = find_element(root, 'div', 'mets') refs = get_attribute(elem_handler, 'DMDID', 'mets').split() set_attribute(elem_handler, 'DMDID', 'mets', '') svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets) assert svrl.count(SVRL_FAILED) == len(refs)