Exemple #1
0
function atomEntry($row, $markupPatternsArray)
{
    global $databaseBaseURL;
    // these variables are defined in 'ini.inc.php'
    global $contentTypeCharset;
    global $fileVisibility;
    global $fileVisibilityException;
    global $filesBaseURL;
    global $convertExportDataToUTF8;
    global $defaultCiteStyle;
    global $citeStyle;
    global $citeOrder;
    global $alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, $print, $punct, $space, $upper, $word, $patternModifiers;
    // defined in 'transtab_unicode_charset.inc.php' and 'transtab_latin1_charset.inc.php'
    // The array '$transtab_refbase_unicode' contains search & replace patterns for conversion from refbase markup to Unicode entities.
    global $transtab_refbase_unicode;
    // defined in 'transtab_refbase_unicode.inc.php'
    // The array '$transtab_refbase_ascii' contains search & replace patterns for conversion from refbase markup to plain text.
    global $transtab_refbase_ascii;
    // defined in 'transtab_refbase_ascii.inc.php'
    // The array '$transtab_refbase_html' contains search & replace patterns for conversion from refbase markup to HTML markup & entities.
    // Note that this will only convert markup which wasn't converted to Unicode entities by '$transtab_refbase_unicode'; this will provide
    // for correct rendering of italic and bold letters in 'content' elements (which is of 'type="xhtml"').
    global $transtab_refbase_html;
    // defined in 'transtab_refbase_html.inc.php'
    // NOTE: We remove again some search & replace patterns that are present by default in '$transtab_refbase_html' since they cause
    //       problems here; this is surely hacky but I don't know any better. :-/
    unset($transtab_refbase_html['/ +- +/']);
    // this would incorrectly convert author initials such as "J. - L." to "J. – L."
    // Define inline text markup to generate a plain text citation string:
    // (to be included within a 'dcterms:bibliographicCitation' element)
    $markupPatternsArrayPlain = array("bold-prefix" => "", "bold-suffix" => "", "italic-prefix" => "", "italic-suffix" => "", "underline-prefix" => "", "underline-suffix" => "", "endash" => "-", "emdash" => "-", "ampersand" => "&", "double-quote" => '"', "double-quote-left" => '"', "double-quote-right" => '"', "single-quote" => "'", "single-quote-left" => "'", "single-quote-right" => "'", "less-than" => "<", "greater-than" => ">", "newline" => "\n");
    // This is a stupid hack that maps the names of the '$row' array keys to those used
    // by the '$formVars' array (which is required by function 'generateCiteKey()')
    // (eventually, the '$formVars' array should use the MySQL field names as names for its array keys)
    $formVars = buildFormVarsArray($row);
    // function 'buildFormVarsArray()' is defined in 'include.inc.php'
    // Generate or extract the cite key for this record:
    // (to be included within a 'dc:identifier' element)
    $citeKey = generateCiteKey($formVars);
    // function 'generateCiteKey()' is defined in 'include.inc.php'
    // Generate OpenURL data:
    // (to be included within a 'dc:identifier' element)
    $openURL = openURL($row, "openurl:");
    // function 'openURL()' is defined in 'openurl.inc.php'
    // Encode special chars and perform charset conversions:
    foreach ($row as $rowFieldName => $rowFieldValue) {
        // We only convert those special chars to entities which are supported by XML:
        // function 'encodeHTMLspecialchars()' is defined in 'include.inc.php'
        $row[$rowFieldName] = encodeHTMLspecialchars($row[$rowFieldName]);
        // Convert field data to UTF-8:
        // (if '$convertExportDataToUTF8' is set to "yes" in 'ini.inc.php' and character encoding is not UTF-8 already)
        // (Note that charset conversion can only be done *after* the cite key has been generated, otherwise cite key
        //  generation will produce garbled text!)
        // function 'convertToCharacterEncoding()' is defined in 'include.inc.php'
        if ($convertExportDataToUTF8 == "yes" and $contentTypeCharset != "UTF-8") {
            $row[$rowFieldName] = convertToCharacterEncoding("UTF-8", "IGNORE", $row[$rowFieldName]);
        }
    }
    // Defines field-specific search & replace 'actions' that will be applied to all those refbase fields that are listed in the corresponding 'fields' element:
    // (If you don't want to perform any search and replace actions, specify an empty array, like: '$fieldSpecificSearchReplaceActionsArray = array();'.
    //  Note that the search patterns MUST include the leading & trailing slashes -- which is done to allow for mode modifiers such as 'imsxU'.)
    //                                          "/Search Pattern/"  =>  "Replace Pattern"
    $fieldSpecificSearchReplaceActionsArray = array();
    if ($convertExportDataToUTF8 == "yes") {
        $fieldSpecificSearchReplaceActionsArray[] = array('fields' => array("title", "publication", "abbrev_journal", "address", "keywords", "abstract", "orig_title", "series_title", "abbrev_series_title", "notes"), 'actions' => $transtab_refbase_unicode);
    }
    // Apply field-specific search & replace 'actions' to all fields that are listed in the 'fields' element of the arrays contained in '$fieldSpecificSearchReplaceActionsArray':
    foreach ($fieldSpecificSearchReplaceActionsArray as $fieldActionsArray) {
        foreach ($row as $rowFieldName => $rowFieldValue) {
            if (in_array($rowFieldName, $fieldActionsArray['fields'])) {
                $row[$rowFieldName] = searchReplaceText($fieldActionsArray['actions'], $rowFieldValue, true);
            }
        }
    }
    // function 'searchReplaceText()' is defined in 'include.inc.php'
    // Fetch the name of the citation style file that's associated with the style given in '$citeStyle':
    $citeStyleFile = getStyleFile($citeStyle);
    // function 'getStyleFile()' is defined in 'include.inc.php'
    if (empty($citeStyleFile)) {
        $citeStyle = $defaultCiteStyle;
        // if the given cite style could not be found, we'll use the default cite style which is defined by the '$defaultCiteStyle' variable in 'ini.inc.php'
        $citeStyleFile = getStyleFile($citeStyle);
    }
    // Include the found citation style file *once*:
    include_once "cite/" . $citeStyleFile;
    // Generate a proper citation for this record, ordering attributes according to the chosen output style & record type:
    // - Plain text version of citation string:
    //   (the plain text version of the citation string will be included in the 'dcterms:bibliographicCitation' element which should contain plain text only)
    $recordCitationPlain = citeRecord($row, $citeStyle, "", $markupPatternsArrayPlain, false);
    // function 'citeRecord()' is defined in the citation style file given in '$citeStyleFile' (which, in turn, must reside in the 'styles' directory of the refbase root directory)
    //   Convert any refbase markup that remains in the citation string (such as _italic_ or **bold**) to plain text:
    $recordCitationPlain = searchReplaceText($transtab_refbase_ascii, $recordCitationPlain, true);
    // - HTML version of citation string:
    //   (note that, for output of Atom XML, we do NOT HTML encode higher ASCII characters; thus, the last param in the below function call is 'false')
    $recordCitation = citeRecord($row, $citeStyle, "", $markupPatternsArray, false);
    //   Convert any refbase markup that remains in the citation string (such as _italic_ or **bold**) into HTML markup:
    //   (the HTML version of the citation string will be included in the Atom 'content' element which uses 'type="xhtml"')
    $recordCitation = searchReplaceText($transtab_refbase_html, $recordCitation, true);
    // Save a plain text version of the title to a new variable:
    // (this will be included in the 'dc:title' element which should contain plain text only)
    $titlePlain = searchReplaceText($transtab_refbase_ascii, $row['title'], true);
    // Convert any remaining refbase markup in the abstract & title to HTML markup:
    // (we use 'type="xhtml"' in the Atom 'title' and 'summary' elements)
    $row['title'] = searchReplaceText($transtab_refbase_html, $row['title'], true);
    $row['abstract'] = searchReplaceText($transtab_refbase_html, $row['abstract'], true);
    // Convert keywords to plain text:
    // (keywords will be written to 'dc:subject' elements which should contain plain text only)
    $row['keywords'] = searchReplaceText($transtab_refbase_ascii, $row['keywords'], true);
    // To avoid advertising email adresses in public Atom XML output, we remove the email address from contents of the
    // 'modified_by' and 'created_by' fields which get displayed in the 'author' and 'content' elements.
    // The following pattern does not attempt to do fancy parsing of email addresses but simply assumes the string format of the
    // 'modified_by' and 'created_by' fields (table 'refs'). If you change the string format, you must modify this pattern as well!
    $creatorName = preg_replace("/(.+?) \\([^)]+\\)/", "\\1", $row['created_by']);
    $editorName = preg_replace("/(.+?) \\([^)]+\\)/", "\\1", $row['modified_by']);
    // Strip any " (ed)" or " (eds)" suffix from author/editor string:
    if (preg_match("/ *\\(eds?\\)\$/", $row['author'])) {
        $row['author'] = preg_replace("/[ \r\n]*\\(eds?\\)/i", "", $row['author']);
    }
    if (preg_match("/ *\\(eds?\\)\$/", $row['editor'])) {
        $row['editor'] = preg_replace("/[ \r\n]*\\(eds?\\)/i", "", $row['editor']);
    }
    // Include a link to any corresponding file if one of the following conditions is met:
    // - the variable '$fileVisibility' (defined in 'ini.inc.php') is set to 'everyone'
    // - the variable '$fileVisibility' is set to 'login' AND the user is logged in
    // - the variable '$fileVisibility' is set to 'user-specific' AND the 'user_permissions' session variable contains 'allow_download'
    // - the array variable '$fileVisibilityException' (defined in 'ini.inc.php') contains a pattern (in array element 1) that matches the contents of the field given (in array element 0)
    //
    // TODO: - the URL-generating code should be made into a dedicated function (since it's shared with 'modsxml.inc.php' and 'oaidcxml.inc.php')
    $printURL = false;
    if ($fileVisibility == "everyone" or $fileVisibility == "login" and isset($_SESSION['loginEmail']) or $fileVisibility == "user-specific" and (isset($_SESSION['user_permissions']) and preg_match("/allow_download/", $_SESSION['user_permissions'])) or !empty($fileVisibilityException) and preg_match($fileVisibilityException[1], $row[$fileVisibilityException[0]])) {
        if (!empty($row['file'])) {
            if (preg_match('#^(https?|ftp|file)://#i', $row['file'])) {
                $URLprefix = "";
                // we don't alter the URL given in the 'file' field
            } else {
                // use the base URL of the standard files directory as prefix:
                if (preg_match('#^/#', $filesBaseURL)) {
                    // absolute path -> file dir is located outside of refbase root dir
                    $URLprefix = 'http://' . $_SERVER['HTTP_HOST'] . $filesBaseURL;
                } else {
                    // relative path -> file dir is located within refbase root dir
                    $URLprefix = $databaseBaseURL . $filesBaseURL;
                }
            }
            $printURL = true;
        }
    }
    // ----------------------------------------------------------
    // Start Atom XML entry:
    $entry = new XML("entry");
    // create an XML object for a single record
    // Add entry-level tags:
    // (not yet used: category, contributor, source, rights)
    // - 'id':
    addNewBranch($entry, "id", array(), $databaseBaseURL . generateURL("show.php", "html", array("record" => $row['serial']), true));
    // - 'title':
    //   TODO: - the 'title' element is required for 'entry', so we may need to insert something else if the record's title is missing
    //		addNewBranch($entry, "title", array("type" => "text"), $titlePlain); // plain text version
    addNewBranch($entry, "title", array("type" => "xhtml"), '<div xmlns="http://www.w3.org/1999/xhtml">' . $row['title'] . '</div>');
    // - 'updated':
    addNewBranch($entry, "updated", array(), generateISO8601TimeStamp($row['modified_date'], $row['modified_time']));
    // function 'generateISO8601TimeStamp()' is defined in 'include.inc.php'
    // - 'published':
    //   NOTE: we use the 'published' element to indicate the date/time when the record was created in the refbase database,
    //         and not when the record's resource was originally published
    addNewBranch($entry, "published", array(), generateISO8601TimeStamp($row['created_date'], $row['created_time']));
    // - 'link':
    //   NOTE: According to the Atom spec, a feed is limited to ONE 'rel=alternate' link per type and hreflang!
    //   A) Main display formats:
    //   - HTML output for this record:
    //     NOTE: How can we output an 'alternate' link to the HTML citation with the same 'type'?
    //           But, maybe, this isn't necessary since a client GUI (layered over the Atom XML data) would expose
    //           the record citation (from the 'content' or 'bibliographicCitation' element) anyhow... ?
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "html", array("record" => $row['serial']), true, "", "", $citeStyle), "alternate", "html", "View record in HTML format");
    // function 'generateURL()' is defined in 'include.inc.php'
    //   B) Export formats
    //   NOTE: should we rather generate 'unapi.php' and 'opensearch.php' URLs where possible?
    //   TODO: add links for ADS, ISI, RSS XML and Word XML
    //   - BibTeX data for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "BibTeX", array("record" => $row['serial']), true), "alternate", "BibTeX", "Export record in BibTeX format");
    //   - Endnote data for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "Endnote", array("record" => $row['serial']), true), "alternate", "Endnote", "Export record in Endnote format");
    //   - RIS data for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "RIS", array("record" => $row['serial']), true), "alternate", "RIS", "Export record in RIS format");
    //   - Atom XML data for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "Atom XML", array("record" => $row['serial']), true, "", "", $citeStyle), "alternate", "Atom XML", "Export record as Atom XML");
    //   - MODS XML data for this record:
    //     NOTE: while we include a link to SRW_MODS XML on feed level, we instead include a link to MODS XML on entry level since the SRW overhead isn't really needed here
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "MODS XML", array("record" => $row['serial']), true), "alternate", "MODS XML", "Export record as MODS XML");
    //   - OAI_DC XML data for this record:
    //     NOTE: A link to MODS XML is already used with this type!
    //		atomLink($entry, $databaseBaseURL . generateURL("show.php", "OAI_DC XML", array("record" => $row['serial']), true, "", "", $citeStyle), "alternate", "OAI_DC XML", "Export record as OAI_DC XML");
    //   - ODF XML data for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "ODF XML", array("record" => $row['serial'], "exportType" => "file"), true), "alternate", "ODF XML", "Export record as ODF XML");
    //   - SRW_DC XML data for this record:
    //     NOTE: A link to MODS XML is already used with this type!
    //		atomLink($entry, $databaseBaseURL . generateURL("show.php", "SRW_DC XML", array("record" => $row['serial']), true, "", "", $citeStyle), "alternate", "SRW_DC XML", "Export record as SRW_DC XML");
    //   - SRW_MODS XML data for this record:
    //     NOTE: A link to MODS XML is already used with this type!
    //		atomLink($entry, $databaseBaseURL . generateURL("show.php", "SRW_MODS XML", array("record" => $row['serial']), true), "alternate", "SRW_MODS XML", "Export record as SRW_MODS XML");
    //   C) Citation formats:
    //   - RTF citations for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "RTF", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "RTF", "Output record as citation in RTF format");
    //   - PDF citations for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "PDF", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "PDF", "Output record as citation in PDF format");
    //   - LaTeX citations for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "LaTeX", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "LaTeX", "Output record as citation in LaTeX format");
    //   - LaTeX .bbl citations for this record:
    //     NOTE: A link to a LaTeX citation is already used with this type!
    //		atomLink($entry, $databaseBaseURL . generateURL("show.php", "LaTeX .bbl", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "LaTeX .bbl", "Output record as citation in LaTeX .bbl format");
    //   - Markdown citations for this record:
    atomLink($entry, $databaseBaseURL . generateURL("show.php", "Markdown", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "Markdown", "Output record as citation in Markdown format");
    //   - ASCII citations for this record:
    //     NOTE: A link to a Markdown citation is already used with this type!
    //		atomLink($entry, $databaseBaseURL . generateURL("show.php", "ASCII", array("record" => $row['serial']), true, "", "", $citeStyle, $citeOrder), "alternate", "ASCII", "Output record as citation in ASCII format");
    //   D) Related links:
    //   - Related URL:
    //     TODO: - the 'type' (and 'title'?) attributes should get adopted if something other than an URL pointing to a HTML page is given
    if (!empty($row['url'])) {
        atomLink($entry, $row['url'], "related", "html", "Web page");
    }
    //   - Related FILE:
    //     NOTE: - should we better use the 'enclosure' element instead?
    //     TODO: - the 'type' attribute should get adopted if something other than PDF is given
    if ($printURL) {
        atomLink($entry, $URLprefix . $row['file'], "related", "PDF", "Electronic full text");
    }
    // - 'author':
    //   NOTE: The Atom 'author' element contains the database user who created this record,
    //         while the publication authors are contained within 'dc:creator' elements
    $recAuthorBranch = new XMLBranch("author");
    $recAuthorBranch->setTagContent($creatorName, "author/name");
    $entry->addXMLBranch($recAuthorBranch);
    // - 'contributor':
    //   NOTE: The Atom 'contributor' element contains the database user who edited this record last,
    //         while the publication editors are contained within 'dc:contributor' elements
    if ($creatorName != $editorName) {
        $recEditorBranch = new XMLBranch("contributor");
        $recEditorBranch->setTagContent($editorName, "contributor/name");
        $entry->addXMLBranch($recEditorBranch);
    }
    // - 'content':
    //   NOTE: According to the Atom spec, all HTML markup must be escaped if 'type="html"' is used. In case of
    //         'type="xhtml"', HTML markup is not entity escaped but must be wrapped in a single XHTML 'div' element.
    //         See: <http://atompub.org/rfc4287.html#element.content>
    //              <http://www.atomenabled.org/developers/syndication/#text>
    //		addNewBranch($entry, "content", array("type" => "html"), encodeHTMLspecialchars($recordCitation));
    addNewBranch($entry, "content", array("type" => "xhtml"), '<div xmlns="http://www.w3.org/1999/xhtml">' . '<div class="unapi"><abbr class="unapi-id" title="' . $databaseBaseURL . generateURL("show.php", "html", array("record" => $row['serial']), true) . '"></abbr></div>' . $recordCitation . '</div>');
    // - 'summary':
    if (!empty($row['abstract'])) {
        addNewBranch($entry, "summary", array("type" => "xhtml"), '<div xmlns="http://www.w3.org/1999/xhtml">' . $row['abstract'] . '</div>');
    }
    // ----------------------------------------------------------
    // Add Dublin Core elements:
    // NOTE: With a few exceptions, we try to adhere to the guidelines given at
    //       "Using simple Dublin Core to describe eprints" by Andy Powell et al.
    //       See: <http://eprints-uk.rdn.ac.uk/project/docs/simpledc-guidelines/>
    // - 'dc:title':
    if (!empty($row['title'])) {
        addMetaElement($entry, "dc", "title", array(), $titlePlain);
    }
    // function 'addMetaElement()' is defined in 'webservice.inc.php'
    // - 'dc:creator':
    //   NOTE: should we use 'foaf:maker' instead of (or in addition to) 'dc:creator'?
    //   ( xmlns:foaf="http://xmlns.com/foaf/0.1/" )
    //
    //   <foaf:maker>
    //     <foaf:Person>
    //       <foaf:name> [ Name of author 1 ] </foaf:name>
    //     </foaf:Person>
    //   </foaf:maker>
    if (!empty($row['author']) and $row['author'] != $row['editor']) {
        addMetaElement($entry, "dc", "creator", array(), $row['author']);
    }
    // - 'dc:creator':
    //   TODO: add refbase corporate author(s) as 'dc:creator'
    // - 'dc:contributor':
    if (!empty($row['editor'])) {
        addMetaElement($entry, "dc", "contributor", array(), $row['editor']);
    }
    // - 'dc:description':
    //   NOTE: since we already use the Atom-native 'summary' element for the record
    //         abstract/summary, we don't add the abstract again as 'dc:description'
    // - 'dc:identifier':
    //   - DOI:
    if (!empty($row['doi'])) {
        addMetaElement($entry, "dc", "identifier", array(), $row['doi'], "doi");
    }
    //   - PMID:
    if (!empty($row['notes']) and preg_match("/PMID *: *\\d+/i", $row['notes'])) {
        addMetaElement($entry, "dc", "identifier", array(), $row['notes'], "pmid");
    }
    //   - arXiv:
    if (!empty($row['notes']) and preg_match("/arXiv *: *[^ ;]+/i", $row['notes'])) {
        addMetaElement($entry, "dc", "identifier", array(), $row['notes'], "arxiv");
    }
    //   - ISBN:
    if (!empty($row['isbn'])) {
        addMetaElement($entry, "dc", "identifier", array(), $row['isbn'], "isbn");
    }
    //   - OpenURL:
    addMetaElement($entry, "dc", "identifier", array(), $openURL, "openurl");
    //   - Cite key:
    addMetaElement($entry, "dc", "identifier", array(), $citeKey, "citekey");
    // - 'dcterms:bibliographicCitation':
    //   NOTE: While Andy Powell (see link above) recommends to put this into a
    //         'dc:identifier' element, we'll put it into a 'dcterms:bibliographicCitation'
    //         element instead, since the citation couldn't be uniquely identified within a
    //         'dc:identifier' element without a 'citation:' prefix (or the like) but that
    //         would be non-standard. Within 'dcterms:bibliographicCitation', the citation
    //         can be uniquely identified and extracted easily.
    //         Compare with 'oaidcxml.inc.php' where, for 'oai_dc:dc' output, we put the
    //         bibliographic citation into a 'dc:identifier' element and use a "citation:"
    //         prefix:
    //		addMetaElement($entry, "dc", "identifier", array(), encodeHTMLspecialchars($recordCitationPlain), "citation");
    addMetaElement($entry, "dcterms", "bibliographicCitation", array(), encodeHTMLspecialchars($recordCitationPlain));
    // - 'dc:source':
    //   NOTE: - In <http://eprints-uk.rdn.ac.uk/project/docs/simpledc-guidelines/>,
    //           Andy Powell et al. recommend that this element should NOT be used!
    //           However, for Atom XML output, we do use the 'dc:source' element for series
    //           info (series title plus volume & issue).
    //           Compare with 'oaidcxml.inc.php' where, for 'oai_dc:dc' output, we also
    //           include publication info in a 'dc:source' element.
    //           Example: <dc:source>Polar Biology, Vol. 25, No. 10</dc:source>
    //   - Series info:
    if (!empty($row['series_title']) or !empty($row['abbrev_series_title'])) {
        if (!empty($row['series_title'])) {
            $series = $row['series_title'];
        } elseif (!empty($row['abbrev_series_title'])) {
            $series = $row['abbrev_series_title'];
        }
        if (!empty($row['series_volume'])) {
            $series .= ", Vol. " . $row['series_volume'];
        }
        if (!empty($row['series_issue'])) {
            $series .= ", No. " . $row['series_issue'];
        }
        if (!empty($series)) {
            addMetaElement($entry, "dc", "source", array(), $series);
        }
        // NOTE: To distinguish between regular publication & series info,
        //       should we better use a "series:" prefix here? If so, use:
        //				addMetaElement($entry, "dc", "source", array(), $series, "series");
    }
    // - 'dc:date':
    if (!empty($row['year'])) {
        addMetaElement($entry, "dc", "date", array(), $row['year']);
    }
    // - 'dc:type':
    if (!empty($row['type'])) {
        addMetaElement($entry, "dc", "type", array(), $row['type'], $row['thesis']);
    }
    //   In case of a thesis, we add another 'dc:type' element with the actual thesis type:
    if (!empty($row['thesis'])) {
        addMetaElement($entry, "dc", "type", array(), $row['thesis']);
    }
    // - 'dc:format':
    //   TODO: ideally, we should parse the content of the refbase 'medium' field and map it
    //         to a media-type term from <http://www.iana.org/assignments/media-types/>
    if (!empty($row['medium'])) {
        $mediaType = $row['medium'];
    } else {
        $mediaType = "text";
    }
    addMetaElement($entry, "dc", "format", array(), $mediaType);
    // - 'dc:subject':
    if (!empty($row['keywords'])) {
        addMetaElement($entry, "dc", "subject", array(), $row['keywords']);
    }
    // - 'dc:coverage':
    //   TODO: should we add contents from the refbase 'area' field as 'dc:coverage' element(s)?
    // - 'dc:relation':
    //   NOTE: currently, we only add 'related' links (and not 'alternate' links) as 'dc:relation'
    //   - Related URL:
    if (!empty($row['url'])) {
        addMetaElement($entry, "dc", "relation", array(), $row['url'], "url");
    }
    //   - Related FILE:
    if ($printURL) {
        addMetaElement($entry, "dc", "relation", array(), $URLprefix . $row['file'], "file");
    }
    // - 'dc:publisher':
    if (!empty($row['publisher'])) {
        addMetaElement($entry, "dc", "publisher", array(), $row['publisher']);
    }
    // - 'dc:language':
    //   TODO: convert to ISO notation (i.e. "en" instead of "English", etc)
    if (!empty($row['language'])) {
        addMetaElement($entry, "dc", "language", array(), $row['language']);
    }
    // ----------------------------------------------------------
    // Add PRISM elements:
    // (not yet used: section)
    // - 'prism:issn':
    //   NOTE: see note for ISBN above
    if (!empty($row['issn'])) {
        addMetaElement($entry, "prism", "issn", array(), $row['issn']);
    }
    // - 'prism:publicationName':
    if (!empty($row['publication'])) {
        addMetaElement($entry, "prism", "publicationName", array(), $row['publication']);
    } elseif (!empty($row['abbrev_journal'])) {
        addMetaElement($entry, "prism", "publicationName", array(), $row['abbrev_journal']);
    }
    // - 'prism:publicationDate':
    if (!empty($row['year'])) {
        addMetaElement($entry, "prism", "publicationDate", array(), $row['year']);
    }
    // - 'prism:volume':
    if (!empty($row['volume'])) {
        addMetaElement($entry, "prism", "volume", array(), $row['volume']);
    }
    // - 'prism:number':
    if (!empty($row['issue'])) {
        addMetaElement($entry, "prism", "number", array(), $row['issue']);
    }
    // - 'prism:startingPage', 'prism:endingPage':
    //   TODO: Similar code is used in 'include.in.php', 'modsxml.inc.php' and 'openurl.inc.php',
    //         so this should be made into a dedicated function!
    if (!empty($row['pages']) and preg_match("/\\d+/i", $row['pages'])) {
        $pages = preg_replace("/^\\D*(\\d+)( *[{$dash}]+ *\\d+)?.*/i{$patternModifiers}", "\\1\\2", $row['pages']);
        // extract page range (if there's any), otherwise just the first number
        $startPage = preg_replace("/^\\D*(\\d+).*/i", "\\1", $row['pages']);
        // extract starting page
        $endPage = extractDetailsFromField("pages", $pages, "/\\D+/", "[-1]");
        // extract ending page (function 'extractDetailsFromField()' is defined in 'include.inc.php')
        // NOTE: To extract the ending page, we'll use function 'extractDetailsFromField()'
        //       instead of just grabbing a matched regex pattern since it'll also work
        //       when just a number but no range is given (e.g. when startPage = endPage)
        // - 'prism:startingPage':
        if (preg_match("/\\d+ *[{$dash}]+ *\\d+/i{$patternModifiers}", $row['pages'])) {
            // if there's a page range
            addMetaElement($entry, "prism", "startingPage", array(), $startPage);
        }
        // - 'prism:endingPage':
        addMetaElement($entry, "prism", "endingPage", array(), $endPage);
    }
    // See also other potentially useful elements from arXiv Atom feeds:
    // (arXiv example: <http://export.arxiv.org/api/query?search_query=all:immunology&id_list=&start=0&max_results=30>)
    //
    // <author>
    //   <name>
    //     Margarita Voitikova
    //   </name>
    //   <arxiv:affiliation xmlns:arxiv="http://arxiv.org/schemas/atom">
    //     Institute of Molecular and Atomic Physics, National Academy of Sciences of Belarus
    //   </arxiv:affiliation>
    // </author>
    //
    // <arxiv:comment xmlns:arxiv="http://arxiv.org/schemas/atom">
    //   6 pages, 3 figures, submitted for publication
    // </arxiv:comment>
    //
    // <arxiv:journal_ref xmlns:arxiv="http://arxiv.org/schemas/atom">
    //   Theory in Biosciences, 123, 431 (2005)
    // </arxiv:journal_ref>
    //
    // <link title="doi" href="http://dx.doi.org/10.1016/j.physd.2005.03.004" rel="related" />
    return $entry;
}
Exemple #2
0
function oaidcRecord($row, $metadataPrefix = "oai_dc", $addNameSpaceInfo = true)
{
    global $databaseBaseURL;
    // these variables are defined in 'ini.inc.php'
    global $contentTypeCharset;
    global $fileVisibility;
    global $fileVisibilityException;
    global $filesBaseURL;
    global $convertExportDataToUTF8;
    global $defaultCiteStyle;
    global $citeStyle;
    global $alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower, $print, $punct, $space, $upper, $word, $patternModifiers;
    // defined in 'transtab_unicode_charset.inc.php' and 'transtab_latin1_charset.inc.php'
    // The array '$transtab_refbase_unicode' contains search & replace patterns for conversion from refbase markup to Unicode entities.
    global $transtab_refbase_unicode;
    // defined in 'transtab_refbase_unicode.inc.php'
    // The array '$transtab_refbase_ascii' contains search & replace patterns for conversion from refbase markup to plain text.
    global $transtab_refbase_ascii;
    // defined in 'transtab_refbase_ascii.inc.php'
    // Define inline text markup to generate a plain text citation string:
    // (to be included within a 'dcterms:bibliographicCitation' element)
    $markupPatternsArrayPlain = array("bold-prefix" => "", "bold-suffix" => "", "italic-prefix" => "", "italic-suffix" => "", "underline-prefix" => "", "underline-suffix" => "", "endash" => "-", "emdash" => "-", "ampersand" => "&", "double-quote" => '"', "double-quote-left" => '"', "double-quote-right" => '"', "single-quote" => "'", "single-quote-left" => "'", "single-quote-right" => "'", "less-than" => "<", "greater-than" => ">", "newline" => "\n");
    // This is a stupid hack that maps the names of the '$row' array keys to those used
    // by the '$formVars' array (which is required by function 'generateCiteKey()')
    // (eventually, the '$formVars' array should use the MySQL field names as names for its array keys)
    $formVars = buildFormVarsArray($row);
    // function 'buildFormVarsArray()' is defined in 'include.inc.php'
    // Generate or extract the cite key for this record:
    // (to be included within a 'dc:identifier' element)
    $citeKey = generateCiteKey($formVars);
    // function 'generateCiteKey()' is defined in 'include.inc.php'
    // Generate OpenURL data:
    // (to be included within a 'dc:identifier' element)
    $openURL = openURL($row, "openurl:");
    // function 'openURL()' is defined in 'openurl.inc.php'
    // Encode special chars and perform charset conversions:
    foreach ($row as $rowFieldName => $rowFieldValue) {
        // We only convert those special chars to entities which are supported by XML:
        // function 'encodeHTMLspecialchars()' is defined in 'include.inc.php'
        $row[$rowFieldName] = encodeHTMLspecialchars($row[$rowFieldName]);
        // Convert field data to UTF-8:
        // (if '$convertExportDataToUTF8' is set to "yes" in 'ini.inc.php' and character encoding is not UTF-8 already)
        // (Note that charset conversion can only be done *after* the cite key has been generated, otherwise cite key
        //  generation will produce garbled text!)
        // function 'convertToCharacterEncoding()' is defined in 'include.inc.php'
        if ($convertExportDataToUTF8 == "yes" and $contentTypeCharset != "UTF-8") {
            $row[$rowFieldName] = convertToCharacterEncoding("UTF-8", "IGNORE", $row[$rowFieldName]);
        }
    }
    // Defines field-specific search & replace 'actions' that will be applied to all those refbase fields that are listed in the corresponding 'fields' element:
    // (If you don't want to perform any search and replace actions, specify an empty array, like: '$fieldSpecificSearchReplaceActionsArray = array();'.
    //  Note that the search patterns MUST include the leading & trailing slashes -- which is done to allow for mode modifiers such as 'imsxU'.)
    //                                          "/Search Pattern/"  =>  "Replace Pattern"
    $fieldSpecificSearchReplaceActionsArray = array();
    if ($convertExportDataToUTF8 == "yes") {
        $fieldSpecificSearchReplaceActionsArray[] = array('fields' => array("title", "publication", "abbrev_journal", "address", "keywords", "abstract", "orig_title", "series_title", "abbrev_series_title", "notes"), 'actions' => $transtab_refbase_unicode);
    }
    // Apply field-specific search & replace 'actions' to all fields that are listed in the 'fields' element of the arrays contained in '$fieldSpecificSearchReplaceActionsArray':
    foreach ($fieldSpecificSearchReplaceActionsArray as $fieldActionsArray) {
        foreach ($row as $rowFieldName => $rowFieldValue) {
            if (in_array($rowFieldName, $fieldActionsArray['fields'])) {
                $row[$rowFieldName] = searchReplaceText($fieldActionsArray['actions'], $rowFieldValue, true);
            }
        }
    }
    // function 'searchReplaceText()' is defined in 'include.inc.php'
    // Fetch the name of the citation style file that's associated with the style given in '$citeStyle':
    $citeStyleFile = getStyleFile($citeStyle);
    // function 'getStyleFile()' is defined in 'include.inc.php'
    if (empty($citeStyleFile)) {
        $citeStyle = $defaultCiteStyle;
        // if the given cite style could not be found, we'll use the default cite style which is defined by the '$defaultCiteStyle' variable in 'ini.inc.php'
        $citeStyleFile = getStyleFile($citeStyle);
    }
    // Include the found citation style file *once*:
    include_once "cite/" . $citeStyleFile;
    // Generate a proper citation for this record, ordering attributes according to the chosen output style & record type:
    // - Plain text version of citation string:
    $recordCitationPlain = citeRecord($row, $citeStyle, "", $markupPatternsArrayPlain, false);
    // function 'citeRecord()' is defined in the citation style file given in '$citeStyleFile' (which, in turn, must reside in the 'styles' directory of the refbase root directory)
    //   Convert any refbase markup that remains in the citation string (such as _italic_ or **bold**) to plain text:
    $recordCitationPlain = searchReplaceText($transtab_refbase_ascii, $recordCitationPlain, true);
    // Convert any remaining refbase markup in the 'title', 'keywords' & 'abstract' fields to plain text:
    $row['title'] = searchReplaceText($transtab_refbase_ascii, $row['title'], true);
    $row['keywords'] = searchReplaceText($transtab_refbase_ascii, $row['keywords'], true);
    $row['abstract'] = searchReplaceText($transtab_refbase_ascii, $row['abstract'], true);
    // Strip any " (ed)" or " (eds)" suffix from author/editor string:
    if (preg_match("/ *\\(eds?\\)\$/", $row['author'])) {
        $row['author'] = preg_replace("/[ \r\n]*\\(eds?\\)/i", "", $row['author']);
    }
    if (preg_match("/ *\\(eds?\\)\$/", $row['editor'])) {
        $row['editor'] = preg_replace("/[ \r\n]*\\(eds?\\)/i", "", $row['editor']);
    }
    // Include a link to any corresponding file if one of the following conditions is met:
    // - the variable '$fileVisibility' (defined in 'ini.inc.php') is set to 'everyone'
    // - the variable '$fileVisibility' is set to 'login' AND the user is logged in
    // - the variable '$fileVisibility' is set to 'user-specific' AND the 'user_permissions' session variable contains 'allow_download'
    // - the array variable '$fileVisibilityException' (defined in 'ini.inc.php') contains a pattern (in array element 1) that matches the contents of the field given (in array element 0)
    //
    // TODO: - the URL-generating code should be made into a dedicated function (since it's shared with 'modsxml.inc.php' and 'atomxml.inc.php')
    $printURL = false;
    if ($fileVisibility == "everyone" or $fileVisibility == "login" and isset($_SESSION['loginEmail']) or $fileVisibility == "user-specific" and (isset($_SESSION['user_permissions']) and preg_match("/allow_download/", $_SESSION['user_permissions'])) or !empty($fileVisibilityException) and preg_match($fileVisibilityException[1], $row[$fileVisibilityException[0]])) {
        if (!empty($row['file'])) {
            if (preg_match('#^(https?|ftp|file)://#i', $row['file'])) {
                $URLprefix = "";
                // we don't alter the URL given in the 'file' field
            } else {
                // use the base URL of the standard files directory as prefix:
                if (preg_match('#^/#', $filesBaseURL)) {
                    // absolute path -> file dir is located outside of refbase root dir
                    $URLprefix = 'http://' . $_SERVER['HTTP_HOST'] . $filesBaseURL;
                } else {
                    // relative path -> file dir is located within refbase root dir
                    $URLprefix = $databaseBaseURL . $filesBaseURL;
                }
            }
            $printURL = true;
        }
    }
    // ----------------------------------------------------------
    // Start OAI_DC XML record:
    if (!empty($metadataPrefix)) {
        $recordPrefix = $metadataPrefix . ":";
    }
    $record = new XML($recordPrefix . "dc");
    // create an XML object for a single record
    if ($addNameSpaceInfo) {
        if ($metadataPrefix == "oai_dc") {
            $record->setTagAttribute("xmlns:oai_dc", "http://www.openarchives.org/OAI/2.0/oai_dc/");
        } elseif ($metadataPrefix == "srw_dc") {
            $record->setTagAttribute("xmlns:srw_dc", "info:srw/schema/1/dc-v1.1");
        }
        $record->setTagAttribute("xmlns:dc", "http://purl.org/dc/elements/1.1/");
        if ($metadataPrefix == "oai_dc") {
            $record->setTagAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
            $record->setTagAttribute("xsi:schemaLocation", "http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd");
        } elseif ($metadataPrefix == "srw_dc") {
            $record->setTagAttribute("xmlns:prism", "http://prismstandard.org/namespaces/1.2/basic/");
        }
    }
    // Add Dublin Core elements:
    // NOTE: With a few exceptions, we try to adhere to the guidelines given at
    //       "Using simple Dublin Core to describe eprints" by Andy Powell et al.
    //       See: <http://eprints-uk.rdn.ac.uk/project/docs/simpledc-guidelines/>
    // - 'dc:title':
    if (!empty($row['title'])) {
        addMetaElement($record, "dc", "title", array(), $row['title']);
    }
    // function 'addMetaElement()' is defined in 'webservice.inc.php'
    // - 'dc:creator':
    if (!empty($row['author']) and $row['author'] != $row['editor']) {
        addMetaElement($record, "dc", "creator", array(), $row['author']);
    }
    // - 'dc:creator':
    //   TODO: add refbase corporate author(s) as 'dc:creator'
    // - 'dc:contributor':
    if (!empty($row['editor'])) {
        addMetaElement($record, "dc", "contributor", array(), $row['editor']);
    }
    // - 'dc:description':
    if (!empty($row['abstract'])) {
        addMetaElement($record, "dc", "description", array(), $row['abstract']);
    }
    // - 'dc:identifier':
    //   - DOI:
    if (!empty($row['doi'])) {
        addMetaElement($record, "dc", "identifier", array(), $row['doi'], "doi");
    }
    //   - PMID:
    if (!empty($row['notes']) and preg_match("/PMID *: *\\d+/i", $row['notes'])) {
        addMetaElement($record, "dc", "identifier", array(), $row['notes'], "pmid");
    }
    //   - arXiv:
    if (!empty($row['notes']) and preg_match("/arXiv *: *[^ ;]+/i", $row['notes'])) {
        addMetaElement($record, "dc", "identifier", array(), $row['notes'], "arxiv");
    }
    //   - ISBN:
    if (!empty($row['isbn'])) {
        addMetaElement($record, "dc", "identifier", array(), $row['isbn'], "isbn");
    }
    //   - OpenURL:
    addMetaElement($record, "dc", "identifier", array(), $openURL, "openurl");
    //   - refbase ID:
    addMetaElement($record, "dc", "identifier", array(), $databaseBaseURL . generateURL("show.php", "html", array("record" => $row['serial']), true), "url");
    //   - Cite key:
    addMetaElement($record, "dc", "identifier", array(), $citeKey, "citekey");
    //   - Bibliographic citation:
    //     NOTE: In 'atomxml.inc.php', the bibliographic citation is put into a
    //           'dcterms:bibliographicCitation' element so that it can be uniquely
    //           identified and extracted easily. However, in case of simple Dublin
    //           Core output, we just put it into a 'dc:identifier' element and
    //           use a "citation:" prefix.
    addMetaElement($record, "dc", "identifier", array(), encodeHTMLspecialchars($recordCitationPlain), "citation");
    // - 'dc:source':
    //   NOTE: - In <http://eprints-uk.rdn.ac.uk/project/docs/simpledc-guidelines/>,
    //           Andy Powell et al. recommend that this element should NOT be used!
    //           However, we use 'dc:source' elements for publication & series info
    //           (publication/series title plus volume & issue) to provide a dedicated
    //           source string that's easily readable and parsable.
    //           Example: <dc:source>Polar Biology, Vol. 25, No. 10</dc:source>
    //         - While we could also append the page info to the publication
    //           'dc:source' element, this info is more pertinent to the article
    //           itself and is thus not included. For 'srw_dc:dc' output, page info is
    //           included in PRISM elements (see below).
    //         - All metadata (including the page info) are also provided as a machine
    //           parsable citation in form of an OpenURL ContextObject (see above).
    //   - Publication info:
    //     NOTE: We only include the 'dc:source' element for 'oai_dc:dc' output. In case of 'srw_dc:dc'
    //           output, we use the more fine-grained PRISM elements instead (see below)
    if ($metadataPrefix == "oai_dc" and (!empty($row['publication']) or !empty($row['abbrev_journal']))) {
        if (!empty($row['publication'])) {
            $source = $row['publication'];
        } elseif (!empty($row['abbrev_journal'])) {
            $source = $row['abbrev_journal'];
        }
        if (!empty($row['volume'])) {
            $source .= ", Vol. " . $row['volume'];
        }
        if (!empty($row['issue'])) {
            $source .= ", No. " . $row['issue'];
        }
        if (!empty($source)) {
            addMetaElement($record, "dc", "source", array(), $source);
        }
    }
    //   - Series info:
    if (!empty($row['series_title']) or !empty($row['abbrev_series_title'])) {
        if (!empty($row['series_title'])) {
            $series = $row['series_title'];
        } elseif (!empty($row['abbrev_series_title'])) {
            $series = $row['abbrev_series_title'];
        }
        if (!empty($row['series_volume'])) {
            $series .= ", Vol. " . $row['series_volume'];
        }
        if (!empty($row['series_issue'])) {
            $series .= ", No. " . $row['series_issue'];
        }
        if (!empty($series)) {
            addMetaElement($record, "dc", "source", array(), $series);
        }
        // NOTE: To distinguish between regular publication & series info,
        //       should we better use a "series:" prefix here? If so, use:
        //				addMetaElement($record, "dc", "source", array(), $series, "series");
    }
    //   - ISSN:
    //     NOTE: for 'srw_dc:dc' output, we put the ISSN into the 'prism:issn' element
    if ($metadataPrefix == "oai_dc" and !empty($row['issn'])) {
        addMetaElement($record, "dc", "source", array(), $row['issn'], "issn");
    }
    // - 'dc:date':
    if (!empty($row['year'])) {
        addMetaElement($record, "dc", "date", array(), $row['year']);
    }
    // - 'dc:type':
    if (!empty($row['type'])) {
        addMetaElement($record, "dc", "type", array(), $row['type'], $row['thesis']);
    }
    //   In case of a thesis, we add another 'dc:type' element with the actual thesis type:
    if (!empty($row['thesis'])) {
        addMetaElement($record, "dc", "type", array(), $row['thesis']);
    }
    // - 'dc:format':
    //   TODO: ideally, we should parse the content of the refbase 'medium' field and map it
    //         to a media-type term from <http://www.iana.org/assignments/media-types/>
    if (!empty($row['medium'])) {
        $mediaType = $row['medium'];
    } else {
        $mediaType = "text";
    }
    addMetaElement($record, "dc", "format", array(), $mediaType);
    // - 'dc:subject':
    //   TODO: add user-specific keywords (from field 'user_keys') if the user is logged in
    if (!empty($row['keywords'])) {
        addMetaElement($record, "dc", "subject", array(), $row['keywords']);
    }
    // - 'dc:coverage':
    //   TODO: should we add contents from the refbase 'area' field as 'dc:coverage' element(s)?
    // - 'dc:relation':
    //   - Related URL:
    if (!empty($row['url'])) {
        addMetaElement($record, "dc", "relation", array(), $row['url'], "url");
    }
    //   - Related FILE:
    if ($printURL) {
        addMetaElement($record, "dc", "relation", array(), $URLprefix . $row['file'], "file");
    }
    // - 'dc:publisher':
    if (!empty($row['publisher'])) {
        addMetaElement($record, "dc", "publisher", array(), $row['publisher']);
    }
    // - 'dc:language':
    //   TODO: convert to ISO notation (i.e. "en" instead of "English", etc)
    if (!empty($row['language'])) {
        addMetaElement($record, "dc", "language", array(), $row['language']);
    }
    // ----------------------------------------------------------
    // Add PRISM elements:
    // NOTE: When using the 'srw_dc' namespace (i.e. 'info:srw/schema/1/dc-v1.1' as detailed at
    //       <http://www.loc.gov/standards/sru/resources/dc-schema.html>), I don't think it's allowed
    //       to include anything but the fifteen elements from simple Dublin Core. Is this correct?
    //       If so, then:
    //
    // TODO: Do we need to put the PRISM elements in <extraRecordData> instead? Or can we put them within
    //       a separate branch outside of (and next to) the '<srw_dc:dc>' element? Or shall we better omit
    //       them entirely?
    //       More info on SRU Extra Data>: <http://www.loc.gov/standards/sru/specs/extra-data.html>
    //
    //       See also "Mixing DC metadata with other metadata schemas" in "Guidelines for implementing
    //       Dublin Core in XML" <http://dublincore.org/documents/dc-xml-guidelines/>
    if ($metadataPrefix == "srw_dc") {
        // - 'prism:issn':
        if (!empty($row['issn'])) {
            addMetaElement($record, "prism", "issn", array(), $row['issn']);
        }
        // - 'prism:publicationName':
        if (!empty($row['publication'])) {
            addMetaElement($record, "prism", "publicationName", array(), $row['publication']);
        } elseif (!empty($row['abbrev_journal'])) {
            addMetaElement($record, "prism", "publicationName", array(), $row['abbrev_journal']);
        }
        // - 'prism:publicationDate':
        if (!empty($row['year'])) {
            addMetaElement($record, "prism", "publicationDate", array(), $row['year']);
        }
        // - 'prism:volume':
        if (!empty($row['volume'])) {
            addMetaElement($record, "prism", "volume", array(), $row['volume']);
        }
        // - 'prism:number':
        if (!empty($row['issue'])) {
            addMetaElement($record, "prism", "number", array(), $row['issue']);
        }
        // - 'prism:startingPage', 'prism:endingPage':
        //   TODO: Similar code is used in 'include.in.php', 'modsxml.inc.php' and 'openurl.inc.php',
        //         so this should be made into a dedicated function!
        if (!empty($row['pages']) and preg_match("/\\d+/i", $row['pages'])) {
            $pages = preg_replace("/^\\D*(\\d+)( *[{$dash}]+ *\\d+)?.*/i{$patternModifiers}", "\\1\\2", $row['pages']);
            // extract page range (if there's any), otherwise just the first number
            $startPage = preg_replace("/^\\D*(\\d+).*/i", "\\1", $row['pages']);
            // extract starting page
            $endPage = extractDetailsFromField("pages", $pages, "/\\D+/", "[-1]");
            // extract ending page (function 'extractDetailsFromField()' is defined in 'include.inc.php')
            // NOTE: To extract the ending page, we'll use function 'extractDetailsFromField()'
            //       instead of just grabbing a matched regex pattern since it'll also work
            //       when just a number but no range is given (e.g. when startPage = endPage)
            // - 'prism:startingPage':
            if (preg_match("/\\d+ *[{$dash}]+ *\\d+/i{$patternModifiers}", $row['pages'])) {
                // if there's a page range
                addMetaElement($record, "prism", "startingPage", array(), $startPage);
            }
            // - 'prism:endingPage':
            addMetaElement($record, "prism", "endingPage", array(), $endPage);
        }
    }
    return $record;
}