Skip to main content
ExLibris
  • Subscribe by RSS
  • Ex Libris Knowledge Center

    Configuring Normalization Rules for External Resources (Primo VE)

    Last updated: March 13, 2024

    Return to menu

    Normalization rules define transformations that are applied to external source records (DC or generic XML) to create the Primo VE expanded Dublin Core records for discovery. You can create your own normalization rules and apply them to externally loaded records.

    Primo VE Administration Certification > External Data Sources (12 min)

    For information on how to create normalization rules for MARC21 records from external sources, see Working with Normalization Rules.

    Using the Expanded DC Schema

    The Primo VE Dublin Core expanded schema includes additional discovery fields that you can populate as needed using normalization rules. The following fields are supported by the expanded DC schema:

    • discovery.resourceType – These fields hold the resource types that display in Primo, which may be different from the values in the dc:type and dcterms:type fields that are loaded from the external records. For more information, see Mapping Resource Types from External Data Sources.

    • discovery.local1 through discovery.local50 – These fields hold additional information that you can use to display additional information from the source and to use as a search index. For more information, see Mapping to Local Discovery Fields.

    Mapping Resource Types from External Data Sources

    Because the values for Dublin Core resource types can be anything and may not match the supported codes used in Primo VE, it may be necessary to map the resource type from the source record's dc:type or dcterms:type field to either a supported resource type code in Primo VE (see Supported Resource Types in Primo VE) or a local resource type defined in Primo VE (see Configuring Resource Types for Primo VE).

    You can use any of the following methods to map the resource types to Primo VE:

    • Create normalization rules that replace the value of the relevant dc:type or dcterms:type field.

    • Create normalization rules that map a resource type value to the the discovery:resourceType field and leave the original DC field as it is.

    • Add resource type mappings to the Dublin Core Type to Discovery Type Mapping mapping table. For more information, see Using the Mapping Table to Map Resource Types.

    Primo VE determines a record's resource type based on the existence of the following fields in order:

    1. discovery:resourceType field

    2. dcterms:type field

    3. dc:type field

    If processing continues to items 2 and 3, the system compares the value of the item with the mappings in the Dublin Core Type to Discovery Type Mapping mapping table. If a match is found, the matching value in the mapping table is used and stored in the discovery:resourceType field. If no match is found and the mapping table has a default value, the default value is used. Otherwise, the system uses the value of the DC field as is.

    Examples

    For more information about creating normalization rules, see Creating Normalization Rules.

    The following example maps the Proceedings resource type in dc:type to a supported code in Primo VE.

    You can map several resource types in the source (such as Poster and Photograph) to the same resource type (such as image) in Primo VE.


    rule "from dc:type A to discovery:type B"

    when

    "dc"."type" equals "Proceedings"

    then

    set "conference_proceedings" in "discovery"."resourceType"

    end


    The following example maps the LibGuides resource type in dcterms:type to a new local resource type that you must define in Primo VE.

    If the local resource type had been defined as LibGuides in Primo VE, the following normalization rule would not be necessary, and the system would just use the resource type that was mapped to dcterms:type in Primo VE.


    rule "from dcterms:type A to discovery:type B"

    when

    "dcterms"."type" equals "LibGuides"

    then

    set "library_guides" in "discovery"."resourceType"

    end


    Supported Resource Types in Primo VE

    The table below lists the resource type codes that are supported by Primo VE. You need to map your source's values to one of the supported codes or a local resource type (if needed). For more information about modifying system resource types and creating local resource types, see Configuring Resource Types for Primo VE.

    Supported Resource Types in Primo VE

    Resource Type Code

    Display Name

    databases

    Database

    audios

    Audio

    newspapers

    Newspaper

    manuscripts

    Manuscript

    conference_proceedings

    Conference Proceeding

    dissertations

    Dissertation

    kits

    Kit

    other

    Other

    archival_materials

    Archival Material

    realia

    Realia

    books

    Book

    book_chapters

    Book Chapter

    collections

    Collection

    legal_documents

    Legal Document

    patents

    Patent

    reference_entrys

    Reference Entry

    research_datasets

    Research Dataset

    reviews

    Review

    statistical_data_sets

    Statistical Data Set

    technical_reports

    Technical Report

    journals

    Journal

    newspaper_articles

    Newspaper Article

    articles

    Article

    text_resources

    Text Resource

    government_documents

    Government Document

    images

    Image

    maps

    Map

    videos

    Video

    scores

    Score

    websites

    Website

    Mapping to Local Discovery Fields

    The Dublin Core expanded schema for Primo VE enables you to map information to the following fields, which are populated during the loading of records: discovery.local1 - discovery.local50. After the records are loaded, Primo VE can use the local fields to display additional information in a record's brief and full displays and also to use them as search fields. Local fields are particularly useful to map non-standard DC fields that are not loaded by default during the import to Primo VE.

    When using a local discovery field, you must also configure its similarly named local display field. For example, if you have created a normalization rule for discovery.local2, you must also define the local display field Local_field_02, making sure that you select the Use the parallel Local Field 01/50 from the Dublin Core record check box. For more information, see Configuring Local Display and Search Fields for Primo VE.

    Examples

    For more information about creating normalization rules, see Creating Normalization Rules.

    The following example maps the value in dc:relation to local field 1 in Primo VE.


    rule "move relation to local field 1"

    when

    exist "dc"."relation"

    then

    move "dc"."relation" to "discovery"."local1"

    end


    The following example sets the value of local field 2 to Internal Research for every record processed.


    rule "set local field 2 for internal research"

    when

    True

    then

    set "Internal Research" in "discovery"."local2"

    end


    Creating Normalization Rules

    The MD Editor enables you to create normalization rules, which are used to customize the transformation of external records (for Dublin Core or generic XML) into Primo VE's extended Dublin Core format for discovery. For external sources using the MARC21 format, Primo VE maps these records to the Alma-MARC21 format for discovery. Once the rules are created, you can add them as needed to normalization rule processes, which can then be assigned to import profiles. For more information, see Creating a Normalization Rule Process.

    To work with normalization rules, you must have any of the following roles:
    • Catalog Administrator
    • Catalog Manager
    • Cataloger
    To add a normalization rule file for external sources:
    1. Open the MD Editor (Configuration Menu > Discovery > Loading External Data Sources > Normalization Rules for External Data Sources).

    2. Select the Rules > Normalization Rules (Discovery) tab and check the existing rules to see if an existing rule can be modified or used as the basis for your new rule.

      PVE_MD_Editor_NR_ExtDataSrc_newMDE.png

      Rules Tab
    3. Create a new rule by selecting either File > New > Normalization (Discovery) for DC/XML rules or File > New > Normalization for MARC21 rules, which depends on the format of the Discovery import files that you are receiving from the external source.

      PVE_NewDCRule2.png

      Configure the Normalization Rule File's Properties
    4. Specify the following properties and then select Save:

      • Name – Specify an identifiable name for the rule file, which may contain related types of rules.

        This field cannot contain single or double quotes: “, ”, ", ‘, ’, and '.

      • Description – Enter text to describe the contents of your rule file.

      • Type - Select either DC, XML, or Drool (MARC21 normalization rules only).

      • Access Level – Select one of the following subfolder locations: Private (for your use only and cannot be included in a normalization process) or Shared (public rule file).

    5. Add your rules to the editor pane. For more information, see Normalization Rule Syntax (DC and Generic XML) or Working with Normalization Rules (MARC21).

      PVE_ME_EditRule_newMDE.png

      Normalization Rule Editor Pane
    6. Select Preview. The rule or rules in the file are applied to the specified records and the outcome appears.

    7. Select Save and Test Using External Record under the editor pane.

    Normalization Rule Syntax for DC and XML Formats

    Rule files contain one or more rules, which contain one or more conditions followed by one or more actions.

    For information regarding the syntax of normalization rules for external MARC21 sources, see Normalization Rule Syntax, which is different from the syntax used to define the normalization rules for the MARC display and local fields that are mapped from bibliographic records managed by Alma.

    The following syntax is used for each rule in the file:


    rule "<rule name>"
    when
    <condition 1>
    <condition 2>
    ...
    then
    <action 1>
    <action 2> [if <condition>]
    ...
    end

    Conditions

    A rule can contain one or more conditions that apply to specific fields and values in the source record. If all conditions are met, the rule is applied to the record. Otherwise, the rule is not applied and the record is left unchanged. Each condition must include one of the following keywords:

    • true – Unconditionally applies the rule to all records.

    • exist – Applies the rule when a specific field exists.

    • not exist – Applies the rule when a specific field does not exist.

    • equals – Applies the rule when the entire contents of the specified field match.

    • not equals – Applies the rule when the entire contents of the specified field does not match.

    The following table provides an example for each type of condition.

    DC and XML Conditions
    Syntax Example
    General Conditions:

    true

    true

    DC Conditions:

    exist "{namespace}"."{field}

    exist "dc"."description"

    exist "{namespace}"."{field}"\("{xsiType}"\)

    exist "dc"."identifier"("dcterms:ISBN")

    "{namespace}"."{field}" equals "{value}"

    "dc"."identifier" equals "sport"

    "{namespace}"."{field}"\("{xsiType}"\) equals "{value}"

    "dc"."identifier"("dcterms:ISBN") equals "sport"

    "{namespace}"."{field}" not equals "{value}"

    "dc"."identifier" not equals "sport"

    "{namespace}"."{field}"\("{xsiType}"\) not equals "{value}"

    "dc"."identifier"("dcterms:ISBN") not equals "sport"

    XML Conditions:

    "xpathExpression" equals "value"

    "ino:object/viaRecord/recordId"  equals "test"

    "xpathExpression" not equals "value"

    "ino:object/viaRecord/recordId"  not equals "test"

    exist "xpathExpression"

    exist "ino:object/viaRecord/recordId"

    not exist "xpathExpression"

    not exist "ino:object/viaRecord/recordId"

    Actions

    You can apply actions to single fields in a record based on conditions specified in the rule. If all the conditions are met, the actions are applied to the record in the order in which they are listed. Each action must include one of the following keywords:

    • copy – Copies the value from one field to another field.

    • move – Moves the value from one field to another field.

    • remove – Removes the value from a field.

    • set – Sets the value of a field directly.

    In some cases, you can append the if equals <value> condition to the above actions to apply rule changes for specific matching values only.

    The following table provides an example for each type of action.

    • String values (such as specified for the rule title and add prefix transformation) cannot contain the subfield separator $$.

    DC and XML Actions
    Syntax Example
    DC Actions:

    copy "{namespace}"."{field}"({"xsiType"}) to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    copy "dc"."identifier"("dcterms:ISBN") to "dc"."title"("dcterms:ISBN")

    copy "{namespace}"."{field}"({"xsiType"}) to "{newTagNameSpace}"."{newTagField}"

    copy "dc"."identifier"("dcterms:ISBN") to "dc"."title"

    copy "{namespace}"."{field}" to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    copy "dc"."identifier" to "dc"."title"("dcterms:ISBN")

    copy "{namespace}"."{field}" to "{newTagNameSpace}"."{newTagField}"

    copy "dc"."identifier" to "dc"."title"

    copy "{namespace}"."{field}"({"xsiType"}) if equals "{value}" to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    copy "dc"."identifier"("dcterms:ISBN") if equals "sport" to "dc"."title"("dcterms:ISBN")

    copy "{namespace}"."{field}"({"xsiType"}) if equals "{value}" to "{newTagNameSpace}"."{newTagField}"

    copy "dc"."identifier"("dcterms:ISBN") if equals "sport" to "dc"."title"

    copy "{namespace}"."{field}" if equals "{value}" to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    copy "dc"."identifier" if equals "sport" to "dc"."title"("dcterms:ISBN")

    copy "{namespace}"."{field}" if equals "{value}" to "{newTagNameSpace}"."{newTagField}"

    copy "dc"."identifier" ") if equals "sport" to "dc"."title"

    move "{namespace}"."{field}"({"xsiType"}) to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    move "dc"."identifier"("dcterms:ISBN") to "dc"."title"("dcterms:ISBN")

    move "{namespace}"."{field}"({"xsiType"}) to "{newTagNameSpace}"."{newTagField}"

    move "dc"."identifier"("dcterms:ISBN") to "dc"."title"

    move "{namespace}"."{field}"  to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    move "dc"."identifier" to "dc"."title"("dcterms:ISBN")

    move "{namespace}"."{field}"  to "{newTagNameSpace}"."{newTagField}"

    move "dc"."identifier" to "dc"."title"

    move "{namespace}"."{field}"({"xsiType"}) to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    move "dc"."identifier"("dcterms:ISBN") if equals "sport" to "dc"."title"("dcterms:ISBN")

    move "{namespace}"."{field}"({"xsiType"}) if equals "{value}"  to "{newTagNameSpace}"."{newTagField}"

    move "dc"."identifier"("dcterms:ISBN") if equals "sport" to "dc"."title"

    move "{namespace}"."{field}" to "{newTagNameSpace}"."{newTagField}"({"newXsiType"})

    move "dc"."identifier" if equals "sport" to "dc"."title"("dcterms:ISBN")

    move "{namespace}"."{field}" if equals "{value}" to "{newTagNameSpace}"."{newTagField}"

    move "dc"."identifier" if equals "sport" to "dc"."title"

    remove "{namespace}"."{field}" if equals "{value}"

    remove "dc"."identifier" if equals "sport"

    remove "{namespace}"."{field}"({"xsiType"}) if equals "{value}"

    remove "dc"."identifier"("dcterms:ISBN") if equals "sport"

    remove "{namespace}"."{field}"({"xsiType"})

    remove "dc"."identifier"("dcterms:ISBN")

    remove "{namespace}"."{field}"

    remove "dc"."identifier"

    set "{value}" in "{namespace}"."{field}"({"xsiType"})

    set "sport" in "dc"."identifier"("dcterms:ISBN")

    set "{value}" in "{namespace}"."{field}"

    set "sport" in "dc"."identifier"

    set "{namespace}"."{field}" to TEMP"{i}"

    set "dc"."identifier" to TEMP"1"

    set "{namespace}"."{field}"("{xsiType}") to TEMP"{i}"

    set "dc"."identifier"("dcterms:ISBN") to TEMP"1"

    set TEMP"{i}" to dc value "{namespace}"."{field}"

    set TEMP"1" to dc value "dc"."identifier"

    set TEMP"{i}" to dc value "{namespace}"."{field}"("{xsiType}")

    set TEMP"1" to dc value "dc"."identifier"("dcterms:ISBN")

    XML Actions: (For more information, see W3C XPATH Standards.)

    copy "concat ({xpathExpression},' ',{xpathExpression})" to "{namespace}"."{field}"

     

    • The concat keyword is an XPATH function, which is one of many XPATH functions that can be used within the XML actions.
    • Due to a Java dependency, we support only functions provided with XPATH version 1.0.

    copy "concat(//person[@pers_role='pau']/name/first/text(),' ',//person[@pers_role='pau']/name/last/text())" to "dc"."creator"

    copy "xpathExpression" to "newTagNameSpace"."newTagField"({"xsiType"})

    copy "ino:object/viaRecord/isbn" to "dcterms"."title"("dcterms:ISBN")

    copy "xpathExpression" to "newTagNameSpace"."newTagField"

    copy "ino:object/viaRecord/isbn" to "dcterms"."title"

    • copy all "{xpathExpression}"\("{separator}"\) to "{newTagNameSpace}"."{newTagField}"

    • copy all "{xpathExpression}"\("{separator}"\)("{newXsiType}"\) to "{newTagNameSpace}"."{newTagField}"

    The copy all action enables you to import more than one instance of a field (such as creator or ISSN) based on a specific separator. To utilize this action, you must create a normalization rule for each instance of the field that you want to support.

    The following example enables you to import a maximum of three creators for each record:

    rule "Rule for creator1"

         when

              exist "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][1]/child::*[local-name()='namePart']"

         then

              copy all "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][1]/child::*[local-name()='namePart']/text()"(", ") to "dc"."creator"

    end

     

    rule "Rule for creator2"

         when

              exist "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][2]/child::*[local-name()='namePart']"

         then

              copy all "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][2]/child::*[local-name()='namePart']/text()"(", ") to "dc"."creator"

    end

     

    rule "Rule for creator3"

         when

              exist "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][3]/child::*[local-name()='namePart']"

         then

              copy all "//*[local-name()='Item']/*[local-name()='Item']/*[local-name()='Component']/*[local-name()='Resource']/*[local-name()='mods']/*[local-name()='name' and @type='personal'][3]/child::*[local-name()='namePart']/text()"(", ") to "dc"."creator"

    end

    set "value" in newTagNameSpace"."newTagField"({"xsiType"})

    set "whatever" in "dcterms"."title"("dcterms:ISBN")

    set "value" in newTagNameSpace"."newTagField"

    set "whatever" in "discovery"."local1"

    set TEMP"{i}" in "{newTagNameSpace}"."{newTagField}"

    set TEMP"2" in "dcterms"."title"

    set TEMP"{i}" in "{newTagNameSpace}"."{newTagField}"("{xsiType}")

    set TEMP"1" in "dcterms"."title"("dcterms:ISBN")

    set TEMP"{i}" to xPath "{xpathExpression}"

    set TEMP"3" to xpath "//datafield[@tag='identifier']"

    Transformation Actions: For both DC and Generic XML, these operations can be used to transform data in the TEMP"i" variable.

    remove substring using regex – This action removes a substring from the contents of a temporary field using a specified regular expression. Valid format:

    remove substring using regexp (TEMP"{i}","<Java_regex >")

    remove substring using regex (TEMP"1","(/|:|;|=|,)+$")

    concatenate with delimiter – This action concatenates the contents of two temporary fields and separates them with a delimiter. The result is placed in the first temporary field. Format:

    concatenate with delimiter (TEMP"{i}",TEMP"{i}","<delimiter>")

    concatenate with delimiter (TEMP"1",TEMP"2","")

    add prefix – This action adds the specified value to the beginning of the temporary field. Valid format:

    add prefix (TEMP"{i}","<value>")

    To add the subfield separator $$Q to the beginning of a temporary field:

    add prefix (TEMP"2","$Q")

    add prefix (TEMP"2","$")

    add suffix – This action adds the specified value to the end of the temporary field. Valid format:

    add suffix (TEMP"{i}","<value>")

    To add the subfield separator $$Q to the end of a temporary field:

    add suffix (TEMP"2","$")

    add suffix (TEMP"2","$Q")

    replace string by string – This action replaces all occurrences of a regular expression with a specified value. Valid format:

    replace string by string (TEMP"{i}","<Java_regex>","<string>")

    replace string by string (TEMP"1","[^0-9]","\\?")

    return list using regex – This action searches for all occurrences of a regular expression in the second temporary field and copies them as a list to the first temporary field. Valid format:

    return list using regex (TEMP"{i}",TEMP"{i}","<Java_regex>")

    return list using regex (TEMP"1",TEMP"2","[a-z]{3}")

    remove string – This action removes a specified string from a temporary field. Valid format:

    remove string (TEMP"{i}","<value>")

    remove string (TEMP"1","<<")

    remove leading and trailing spaces – This action removes beginning and trailing spaces in a temporary field. Valid format:

    remove leading and trailing spaces (TEMP"{i}")

    remove leading and trailing spaces (TEMP"1")

    replace spaces – This action replaces all spaces in a temporary field with a specified character or string. Valid format:

    replace spaces (TEMP"{i}","<string>")

    replace spaces (TEMP"1"," ")

    lower case – This action changes all letters in a temporary field to lowercase. Valid format:

    lower case (TEMP"{i}")

    lower case (TEMP"1")

    DC Examples

     

     
    rule "add OA indication"
    when
    True
    then
    set "Unrestricted online access" in "dcterms"."accessRights"
    end

     
    rule "move description"
    when
    exist "dc"."description"
    then
    move "dc"."description" to "dcterms"."description"
    end

     
    rule "move description"
    when
    exist "dc"."identifier"("dcterms:ISBN")
    then
    move "dc"."identifier"("dcterms:ISBN") to "dcterms"."identifier"("dcterms:ISBN")
    end

     
    rule "move description"
    when
    "dc"."identifier"("dcterms:ISBN") equals "sport1111"
    then
    move "dc"."identifier"("dcterms:ISBN") to "dcterms"."identifier"("dcterms:ISBN")
    end

     
    rule "dc identifier equals sport"
    when
    "dc"."identifier"("dcterms:ISBN") not equals "sport"
    then
    move "dc"."title" to "dcterms"."description"
    end

     
    rule "from dc:type A to discovery:type C"
    when
    "dc"."type" equals "Photograph"
    then
    set "images" in "discovery"."resourceType"
    end

     
    rule "from dc:type A to discovery:type D"
    when
    "dc"."type" equals "Poster"
    then
    set "images" in "discovery"."resourceType"
    end

    XML Examples

     

     
    rule "link to resource"
    when
    true
    then
    copy "//*[local-name()='dc']/*[local-name()='identifier'][starts-with(., 'https://www.e.myInst')]/." to "dc"."source"
    end

     
    rule "Copy identifier"
    when
    exist "ino:object/viaRecord/recordId"
    then
    copy "ino:object/viaRecord/recordId" to "dc"."identifier"
    end

     

    rule "copy first title"
    when
    true
    then
    copy "(//title/textElement)[1]" to "dc"."title"
    end

     

    rule "copy all titles"
    when
    true
    then
    copy "(//title/textElement)" to "dcterms"."title"
    end

     

    rule "creator"
    when
    exist "ino:object/viaRecord/work/creator/nameElement"
    then
    copy "ino:object/viaRecord/work/creator/nameElement" to "dc"."creator"
    end

     

    rule "equals english"
    when
    "ino:object/viaRecord/work/lang/textElement" equals "eng"
    then
    set "English" in "dc"."language"
    end

     

    rule "set Constant"
    when
    true
    then
    set "test subject" in "dc"."subject"
    end

    • Was this article helpful?