Пример #1
0
def test_rightsstatement_warning(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.5.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, _) = parse_xml_string(xml)

    # rightsStatement gives a warning with specification 1.5.0
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 0
    assert svrl.count(SVRL_REPORT) == 1
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_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
Пример #4
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
Пример #5
0
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_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_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
Пример #8
0
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
Пример #9
0
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_mets_root(schematron_fx):
    """Test that other root elements than METS are not allowed.

    :schematron_fx: Schematron compile fixture
    """
    xml = '''<premis:premis xmlns:premis="%(premis)s"/>''' % NAMESPACES
    (xmltree, _) = parse_xml_string(xml)
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=xmltree)
    assert svrl.count(SVRL_FAILED) == 1
def test_container():
    """Test container addition
    """
    (_, root
     ) = parse_xml_string('<mets:foo xmlns:mets="http://www.loc.gov/METS/"/>')
    (_, root) = add_containers(root, 'mets:mets/mets:amdSec')
    xml = b'<mets:mets xmlns:mets="http://www.loc.gov/METS/">' \
        b'<mets:amdSec><mets:foo/></mets:amdSec></mets:mets>'
    assert ET.tostring(root) == xml
def test_identifiers_unique(schematron_fx):
    """Test that check for PREMIS identifiers are unique works. We give 8
    PREMIS sections with same identifiers, and loop those unique one by one.
    Finally, when all are unique, no errors are expected.

    :schematron_fx: Schematron compile fixture
    """
    xml = '''<mets:techMD><mets:mdWrap><mets:xmlData><premis:object><premis:objectIdentifier>
                 <premis:objectIdentifierType>local
                 </premis:objectIdentifierType>
                 <premis:objectIdentifierValue>xxx
                 </premis:objectIdentifierValue>
               </premis:objectIdentifier></premis:object></mets:xmlData></mets:mdWrap></mets:techMD>
             <mets:rightsMD><mets:mdWrap><mets:xmlData><premis:rights><premis:rightsStatement>
               <premis:rightsStatementIdentifier>
                 <premis:rightsStatementIdentifierType>local
                 </premis:rightsStatementIdentifierType>
                 <premis:rightsStatementIdentifierValue>xxx
                 </premis:rightsStatementIdentifierValue>
               </premis:rightsStatementIdentifier></premis:rightsStatement>
             </premis:rights></mets:xmlData></mets:mdWrap></mets:rightsMD>
             <mets:digiprovMD><mets:mdWrap><mets:xmlData><premis:event><premis:eventIdentifier>
                 <premis:eventIdentifierType>local</premis:eventIdentifierType>
                 <premis:eventIdentifierValue>xxx</premis:eventIdentifierValue>
               </premis:eventIdentifier></premis:event></mets:xmlData></mets:mdWrap></mets:digiprovMD>
             <mets:digiprovMD><mets:mdWrap><mets:xmlData><premis:agent><premis:agentIdentifier>
                 <premis:agentIdentifierType>local</premis:agentIdentifierType>
                 <premis:agentIdentifierValue>xxx</premis:agentIdentifierValue>
               </premis:agentIdentifier></premis:agent></mets:xmlData></mets:mdWrap>
             </mets:digiprovMD>'''
    head = '''<mets:mets fi:CATALOG="1.5.0" xmlns:mets="%(mets)s"
               xmlns:premis="%(premis)s" xmlns:fi="%(fikdk)s"
               PROFILE="http://www.kdk.fi/kdk-mets-profile" OBJID="bbb">
              <mets:metsHdr/><mets:dmdSec/><mets:amdSec>''' \
              % NAMESPACES
    tail = '''</mets:amdSec><mets:structMap/></mets:mets>'''
    (mets, root) = parse_xml_string(head + xml + xml + tail)

    # Errors with specification 1.5.0, we fix the identifiers one by one.
    number = 0
    for idtag in [
            'objectIdentifierValue', 'rightsStatementIdentifierValue',
            'eventIdentifierValue', 'agentIdentifierValue'
    ]:
        for tag in find_all_elements(root, idtag, 'premis'):
            svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
            number = number + 1
            tag.text = 'xxx' + str(number)
            if number < 8:
                assert svrl.count(SVRL_FAILED) == 1
            else:
                assert svrl.count(SVRL_FAILED) == 0
def test_mandatory_sections_root(schematron_fx):
    """Attributes @PROFILE and @OBJID are required. Metadata sectons are
    required: (1) mets header, (2) dmdSec with standard metadata format,
    (3) techMD, (4) digiprovMD. All of these should give one error,
    if just METS root is given.

    :schematron_fx: Schematron compile fixture
    """
    xml = '''<mets:mets xmlns:mets="%(mets)s"/>''' \
          % NAMESPACES
    (mets, _) = parse_xml_string(xml)
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 6
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 test_charset_parameter(schematron_fx, fileformat):
    """Text file format require character set info in the formatName from
    specification 1.5.0. Test all allowed character sets.

    :schematron_fx: Schematron compile fixture
    :fileformat: Text file format
    """
    xml = '''<mets:mets fikdk:CATALOG="1.5.0" xmlns:mets="%(mets)s"
             xmlns:premis="%(premis)s" xmlns:fikdk="%(fikdk)s"><mets:amdSec>
             <mets:techMD><mets:mdWrap MDTYPEVERSION="2.3"><mets:xmlData>
               <premis:object><premis:objectCharacteristics>
                 <premis:format><premis:formatDesignation>
                 <premis:formatName/></premis:formatDesignation>
               </premis:format></premis:objectCharacteristics>
               </premis:object></mets:xmlData></mets:mdWrap>
             </mets:techMD></mets:amdSec></mets:mets>''' % NAMESPACES
    charsets = [
        'ISO-8859-15', 'UTF-8', 'UTF-16', 'UTF-32', 'iso-8859-15', 'utf-8',
        'utf-16', 'utf-32'
    ]
    (mets, root) = parse_xml_string(xml)
    elem_handler = find_element(root, 'formatName', 'premis')
    elem_handler.text = fileformat

    # Error, since charset is missing
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 1

    # All valid caharcter sets work
    for charset in charsets:
        elem_handler.text = fileformat + ';charset=' + charset
        svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
        assert svrl.count(SVRL_FAILED) == 0

    # Arbitrary character set is disallowed
    elem_handler.text = fileformat + ';charset=xxx'
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 1

    # Character set not required with arbitrary formats
    elem_handler.text = 'xxx'
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 0
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
Пример #17
0
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_ead3_extension(schematron_fx, xml, failures):
    """Test the rule which checks the content of the <objectxmlwrap> element in
       EAD3. It may contain any elements, but only outside EAD3 namespace.

    :schematron_fx: Schematron compile fixture
    :xml: XML to be validated
    :failures: Number of Schematron failures to expect
    """
    (xmltree, root) = parse_xml_string(xml)
    (xmltree, mets_root) = add_containers(
        root, 'mets:mets/mets:dmdSec/mets:mdWrap/mets:xmlData/ead3:ead')
    mdwrap = find_element(mets_root, 'mdWrap', 'mets')
    set_attribute(mdwrap, 'MDTYPEVERSION', 'mets', '1.0.0')
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=xmltree, params=False)
    assert svrl.count(SVRL_FIRED) == 1
    assert svrl.count(SVRL_FAILED) == failures

    set_attribute(mdwrap, 'MDTYPEVERSION', 'mets', '1.1.0')
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=xmltree, params=False)
    assert svrl.count(SVRL_FIRED) == 0
def test_mdtype_namespace(schematron_fx, section, mdinfo):
    """Test that the check for comparing given metadata type and the actual
    metadata works.

    :schematron_fx: Schematron compile fixture
    :section: Context section to be tested
    :mdinfo: Working metadata info: [MDTYPE, OTHERMDTYPE, MDTYPEVERSION,
             root element in the metadata section, namespace of the root]
    """
    xml = '''<mets:mets fi:CATALOG="1.6.0" xmlns:mets="%(mets)s"
             xmlns:premis="%(premis)s" xmlns:fi="%(fikdk)s" xmlns:dc="%(dc)s"
             xmlns:marc21="%(marc21)s" xmlns:ead="%(ead)s"
             xmlns:ead3="%(ead3)s" xmlns:lido="%(lido)s" xmlns:vra="%(vra)s"
              xmlns:mods="%(mods)s" xmlns:eac="%(eac)s"
              xmlns:ddilc32="%(ddilc32)s" xmlns:ddilc31="%(ddilc31)s"
              xmlns:ddicb25="%(ddicb25)s" xmlns:ddicb21="%(ddicb21)s"
              xmlns:mix="%(mix)s"
              xmlns:addml="%(addml)s" xmlns:audiomd="%(audiomd)s"
              xmlns:videomd="%(videomd)s">
               <mets:dmdSec><mets:mdWrap MDTYPE='DC' MDTYPEVERSION='1.1'>
                 <mets:xmlData>
                 <dc:subject/></mets:xmlData></mets:mdWrap></mets:dmdSec>
               <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: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:rights/></mets:xmlData></mets:mdWrap>
               </mets:rightsMD>
               <mets:rightsMD>
                 <mets:mdWrap MDTYPE="PREMIS:RIGHTS" MDTYPEVERSION='2.3'>
                 <mets:xmlData><premis:rights/></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: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)
    if mdinfo[1] == 'DATACITE':
        fix_version_17(root)

    # Test that the given combination works
    elem_section = find_element(root, section, 'mets')
    elem_wrap = find_element(elem_section, 'mdWrap', 'mets')
    set_attribute(elem_wrap, 'MDTYPE', 'mets', mdinfo[0])
    if mdinfo[1] is not None:
        set_attribute(elem_wrap, 'OTHERMDTYPE', 'mets', mdinfo[1])
    set_attribute(elem_wrap, 'MDTYPEVERSION', 'mets', mdinfo[2])
    elem_handler = find_element(elem_wrap, 'xmlData', 'mets')
    elem_handler.clear()
    set_element(elem_handler, mdinfo[3], mdinfo[4])
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 0

    # Wrong (empty) namespace
    elem_handler.clear()
    set_element(elem_handler, mdinfo[3], None)
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 1

    # Arbitrary MDTYPE (wrong)
    set_attribute(elem_wrap, 'MDTYPE', 'mets', 'xxx')
    if mdinfo[1] is not None:
        del_attribute(elem_wrap, 'OTHERMDTYPE', 'mets')
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    set_attribute(elem_wrap, 'MDTYPE', 'mets', mdinfo[0])
    if mdinfo[1] is not None:
        set_attribute(elem_wrap, 'OTHERMDTYPE', 'mets', mdinfo[1])
    assert svrl.count(SVRL_FAILED) == 1

    # Arbitrary MDTYPEVERSION (wrong)
    set_attribute(elem_wrap, 'MDTYPEVERSION', 'mets', 'xxx')
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    set_attribute(elem_wrap, 'MDTYPEVERSION', 'mets', mdinfo[2])
    assert svrl.count(SVRL_FAILED) == 1

    # Check that the metadata fails in other sections
    for othersection in ['dmdSec', 'techMD', 'rightsMD', 'digiprovMD']:
        if othersection != section:
            svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
            assert svrl.count(SVRL_FAILED) == 1
def test_linking_premis(schematron_fx):
    """Test that check of PREMIS links work. A linking element must have a
    corresponding PREMIS section. We give lniks to 8 PREMIS sections without
    the sections. Then we add the required sections one by one.

    :schematron_fx: Schematron compile fixture
    """
    xml = '''<mets:mets fi:CATALOG="1.5.0" xmlns:mets="%(mets)s"
             xmlns:premis="%(premis)s" xmlns:fi="%(fikdk)s">
             <mets:amdSec><mets:techMD><mets:mdWrap><mets:xmlData>
               <premis:object><premis:linkingEventIdentifier>
                   <premis:linkingEventIdentifierType>local
                   </premis:linkingEventIdentifierType>
                   <premis:linkingEventIdentifierValue>event-001
                   </premis:linkingEventIdentifierValue>
                 </premis:linkingEventIdentifier>
                 <premis:linkingRightsStatementIdentifier>
                   <premis:linkingRightsStatementIdentifierType>local
                   </premis:linkingRightsStatementIdentifierType>
                   <premis:linkingRightsStatementIdentifierValue>rights-001
                   </premis:linkingRightsStatementIdentifierValue>
                 </premis:linkingRightsStatementIdentifier>
             </premis:object></mets:xmlData></mets:mdWrap></mets:techMD>
             <mets:rightsMD><mets:mdWrap><mets:xmlData><premis:rights>
               <premis:rightsStatement><premis:linkingObjectIdentifier>
                   <premis:linkingObjectIdentifierType>local
                   </premis:linkingObjectIdentifierType>
                   <premis:linkingObjectIdentifierValue>object-001
                   </premis:linkingObjectIdentifierValue>
                 </premis:linkingObjectIdentifier>
                 <premis:linkingAgentIdentifier>
                   <premis:linkingAgentIdentifierType>local
                   </premis:linkingAgentIdentifierType>
                   <premis:linkingAgentIdentifierValue>agent-001
                   </premis:linkingAgentIdentifierValue>
               </premis:linkingAgentIdentifier></premis:rightsStatement>
             </premis:rights></mets:xmlData></mets:mdWrap></mets:rightsMD>
             <mets:digiprovMD><mets:mdWrap><mets:xmlData><premis:event>
                 <premis:linkingAgentIdentifier>
                   <premis:linkingAgentIdentifierType>local
                   </premis:linkingAgentIdentifierType>
                   <premis:linkingAgentIdentifierValue>agent-001
                   </premis:linkingAgentIdentifierValue>
                 </premis:linkingAgentIdentifier>
                 <premis:linkingObjectIdentifier>
                   <premis:linkingObjectIdentifierType>local
                   </premis:linkingObjectIdentifierType>
                   <premis:linkingObjectIdentifierValue>object-001
                   </premis:linkingObjectIdentifierValue>
                 </premis:linkingObjectIdentifier></premis:event>
             </mets:xmlData></mets:mdWrap></mets:digiprovMD>
             <mets:digiprovMD><mets:mdWrap><mets:xmlData><premis:agent>
                 <premis:linkingEventIdentifier>
                   <premis:linkingEventIdentifierType>local
                   </premis:linkingEventIdentifierType>
                   <premis:linkingEventIdentifierValue>event-001
                   </premis:linkingEventIdentifierValue>
                 </premis:linkingEventIdentifier>
                 <premis:linkingRightsStatementIdentifier>
                   <premis:linkingRightsStatementIdentifierType>local
                   </premis:linkingRightsStatementIdentifierType>
                   <premis:linkingRightsStatementIdentifierValue>rights-001
                   </premis:linkingRightsStatementIdentifierValue>
                 </premis:linkingRightsStatementIdentifier></premis:agent>
             </mets:xmlData></mets:mdWrap></mets:digiprovMD></mets:amdSec>
             </mets:mets>''' % NAMESPACES

    (mets, root) = parse_xml_string(xml)

    # Eight dead links
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 8

    # Object section added, six dead links
    elem_handler = find_element(root, 'object', 'premis')
    xml_id = '''<premis:objectIdentifier xmlns:premis="%(premis)s">
                <premis:objectIdentifierType>local
                </premis:objectIdentifierType>
                <premis:objectIdentifierValue>object-001
                </premis:objectIdentifierValue>
                </premis:objectIdentifier>''' % NAMESPACES
    elem_handler.insert(0, ET.fromstring(xml_id))
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 6

    # Event section added, four dead links
    elem_handler = find_element(root, 'event', 'premis')
    xml_id = '''<premis:eventIdentifier xmlns:premis="%(premis)s">
                <premis:eventIdentifierType>local
                </premis:eventIdentifierType>
                <premis:eventIdentifierValue>event-001
                </premis:eventIdentifierValue>
                </premis:eventIdentifier>''' % NAMESPACES
    elem_handler.insert(0, ET.fromstring(xml_id))
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 4

    # Agent section added, two dead links
    elem_handler = find_element(root, 'agent', 'premis')
    xml_id = '''<premis:agentIdentifier xmlns:premis="%(premis)s">
                <premis:agentIdentifierType>local
                </premis:agentIdentifierType>
                <premis:agentIdentifierValue>agent-001
                </premis:agentIdentifierValue>
                </premis:agentIdentifier>''' % NAMESPACES
    elem_handler.insert(0, ET.fromstring(xml_id))
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 2

    # Rights section added, no dead links
    elem_handler = find_element(root, 'rightsStatement', 'premis')
    xml_id = '''<premis:rightsStatementIdentifier xmlns:premis="%(premis)s">
                <premis:rightsStatementIdentifierType>local
                </premis:rightsStatementIdentifierType>
                <premis:rightsStatementIdentifierValue>rights-001
                </premis:rightsStatementIdentifierValue>
                </premis:rightsStatementIdentifier>''' \
             % NAMESPACES
    elem_handler.insert(0, ET.fromstring(xml_id))
    svrl = schematron_fx(schematronfile=SCHFILE, xmltree=mets)
    assert svrl.count(SVRL_FAILED) == 0