Esempio n. 1
0
        }
        // remove the first array element (i.e. remove the oldest query) if there are more than 30 saved queries
        saveSessionVariable("queryHistory", $queryHistory);
    }
}
// Second, save the generated query to a session variable:
// NOTE: we exclude queries for export formats & citation formats other than HTML
//       (otherwise the history list would contain links to non-HTML content such as RTF or BibTeX files)
if ($displayType != "Export" and preg_match("/^html\$/i", $citeType)) {
    $queryParametersArray = array("sqlQuery" => $query, "client" => $client, "formType" => "sqlSearch", "submit" => $displayType, "viewType" => $viewType, "showQuery" => $showQuery, "showLinks" => $showLinks, "showRows" => $showRows, "rowOffset" => $rowOffset, "wrapResults" => $wrapResults, "citeOrder" => $citeOrder, "citeStyle" => $citeStyle, "exportFormat" => $exportFormat, "exportType" => $exportType, "exportStylesheet" => $exportStylesheet, "citeType" => $citeType, "headerMsg" => $headerMsg);
    saveSessionVariable("oldQuery", $queryParametersArray);
}
// Third, find out how many rows are available and (if there were rows found) seek to the current offset:
// Note that the 'seekInMySQLResultsToOffset()' function will also (re-)assign values to the variables
// '$rowOffset', '$showRows', '$rowsFound', '$previousOffset', '$nextOffset' and '$showMaxRow'.
list($result, $rowOffset, $showRows, $rowsFound, $previousOffset, $nextOffset, $showMaxRow) = seekInMySQLResultsToOffset($result, $rowOffset, $showRows, $displayType, $citeType);
// function 'seekInMySQLResultsToOffset()' is defined in 'include.inc.php'
// If the current result set contains multiple records, we save the generated query URL to yet another session variable:
// (after a record has been successfully added/edited/deleted, this query will be included as a link ["Display previous search results"] in the feedback header message
//  if the SQL query in 'oldQuery' is different from that one stored in 'oldMultiRecordQuery', i.e. if 'oldQuery' points to a single record)
if ($rowsFound > 1 and $displayType != "Export" and preg_match("/^html\$/i", $citeType)) {
    // as above, we exclude queries for export formats & citation formats other than HTML
    saveSessionVariable("oldMultiRecordQuery", $queryParametersArray);
}
// Fourth, setup an array of arrays holding URL and title information for all RSS/Atom feeds available on this page:
// (appropriate <link...> tags will be included in the HTML header for every URL specified)
$rssURLArray = array();
if (isset($_SESSION['user_permissions']) and preg_match("/allow_rss_feeds/", $_SESSION['user_permissions'])) {
    // ...extract the 'WHERE' clause from the SQL query to include it within the feed URL:
    $queryWhereClause = extractWHEREclause($query);
    // function 'extractWHEREclause()' is defined in 'include.inc.php'
Esempio n. 2
0
function srwCollection($result, $rowOffset, $showRows, $exportStylesheet, $displayType)
{
    global $contentTypeCharset;
    // these variables are defined in 'ini.inc.php'
    global $convertExportDataToUTF8;
    global $exportFormat;
    // this is needed so that we can distinguish between "SRW_DC XML" and "SRW_MODS XML" record formats
    // 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'
    global $fieldSpecificSearchReplaceActionsArray;
    // Individual records are objects and collections of records are strings
    // 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);
    }
    $srwCollectionDoc = new XMLDocument();
    if ($convertExportDataToUTF8 == "yes" and $contentTypeCharset != "UTF-8") {
        $srwCollectionDoc->setEncoding("UTF-8");
    } else {
        $srwCollectionDoc->setEncoding($contentTypeCharset);
    }
    $srwCollection = srwGenerateBaseTags("searchRetrieveResponse");
    $showRowsOriginal = $showRows;
    // save original value of '$showRows' (which may get modified by the 'seekInMySQLResultsToOffset()' function below)
    // Find out how many rows are available and (if there were rows found) seek to the current offset:
    // function 'seekInMySQLResultsToOffset()' is defined in 'include.inc.php'
    list($result, $rowOffset, $showRows, $rowsFound, $previousOffset, $nextOffset, $showMaxRow) = seekInMySQLResultsToOffset($result, $rowOffset, $showRows, $displayType, "");
    addNewBranch($srwCollection, "srw:numberOfRecords", array(), $rowsFound);
    // function 'addNewBranch()' is defined in 'webservice.inc.php'
    // <srw:resultSetId> not supported
    // <srw:resultSetIdleTime> not supported
    $srwRecordsBranch = new XMLBranch("srw:records");
    if ($showRowsOriginal != 0) {
        $exportArray = array();
        // Array for individually exported records
        // Generate the export for each record and push them onto an array:
        for ($rowCounter = 0; $rowCounter < $showRows && ($row = @mysql_fetch_array($result)); $rowCounter++) {
            if (preg_match("/DC/i", $exportFormat)) {
                // export the current record as DC XML (i.e. simple Dublin Core):
                $record = oaidcRecord($row, "srw_dc");
            } else {
                // by default, we export the current record as MODS XML:
                $record = modsRecord($row);
            }
            // function 'modsRecord()' is defined in 'modsxml.inc.php'
            // TODO: build 'extraRecordData' for OAI-PMH (see below) using:
            //       $row['serial'], $row['modified_date'], $row['modified_time']
            if (!empty($record)) {
                // unless the record buffer is empty...
                array_push($exportArray, $record);
            }
            // ...add it to an array of exports
        }
        $i = $rowOffset;
        // initialize counter
        // for each of the DC/MODS records in the result set...
        foreach ($exportArray as $record) {
            ++$i;
            // increment $i by one, then return $i
            $srwRecordBranch = new XMLBranch("srw:record");
            if (preg_match("/DC/i", $exportFormat)) {
                srwGeneratePackingSchema($srwRecordBranch, "xml", "dc");
            } else {
                srwGeneratePackingSchema($srwRecordBranch, "xml", "mods");
            }
            $srwRecordDataBranch = new XMLBranch("srw:recordData");
            if (preg_match("/MODS/i", $exportFormat)) {
                // NOTE: converting the MODS object into a string to perform search & replace actions
                //       may be very clumsy but I don't know any better... ?:-/
                $recordString = $record->getXMLString();
                $recordString = preg_replace('/<mods/i', '<mods xmlns="http://www.loc.gov/mods/v3"', $recordString);
                // alternatively to the above line we could add a 'mods:' identifier to all MODS XML tags:
                //				$recordString = preg_replace("#<(/)?#","<\\1mods:",$recordString);
                $record->removeAllBranches();
                $record->parseFromString($recordString);
            }
            $srwRecordDataBranch->addXMLasBranch($record);
            $srwRecordBranch->addXMLBranch($srwRecordDataBranch);
            // TODO: add 'extraRecordData' for OAI-PMH as explained in <http://www.dlib.org/dlib/february05/sanderson/02sanderson.html>
            //       Example:
            //                <extraRecordData>
            //                    <oai:header xmlns:oai="http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
            //                        <oai:identifier>...</oai:identifier>
            //                        <oai:datestamp>...</oai:datestamp>
            //                        <oai:setSpec>...</oai:setSpec>
            //                    </oai:header>
            //                </extraRecordData>
            //
            //       Then add to the SRW 'Explain' response:
            //          1.  an oai.identifier index containing a unique identifier for each record in the database
            //          2.  an oai.datestamp index containing the date/time the record was added or changed in the database
            //          3.  an optional oai.set index, browsable via the scan operation, to support selective harvesting of records
            addNewBranch($srwRecordBranch, "srw:recordPosition", array(), $i);
            $srwRecordsBranch->addXMLBranch($srwRecordBranch);
        }
    }
    $srwCollection->addXMLBranch($srwRecordsBranch);
    if ($showRowsOriginal != 0 && $showMaxRow < $rowsFound) {
        // show 'nextRecordPosition' if the SRU query did not contain 'maximumRecords=0' and if there are any remaining records to be displayed
        addNewBranch($srwCollection, "srw:nextRecordPosition", array(), $showMaxRow + 1);
    }
    $srwCollectionDoc->setXML($srwCollection);
    $srwCollectionString = $srwCollectionDoc->getXMLString();
    // Add the XML Stylesheet definition:
    // Note that this is just a hack (that should get fixed) since I don't know how to do it properly using the ActiveLink PHP XML Package ?:-/
    if (!empty($exportStylesheet)) {
        $srwCollectionString = preg_replace("/(?=\\<srw:searchRetrieveResponse)/i", "<?xml-stylesheet type=\"text/xsl\" href=\"" . $exportStylesheet . "\"?>\n", $srwCollectionString);
    }
    return $srwCollectionString;
}
Esempio n. 3
0
function atomCollection($result, $rowOffset, $showRows, $exportStylesheet, $displayType)
{
    global $databaseBaseURL;
    // these variables are defined in 'ini.inc.php'
    global $contentTypeCharset;
    global $convertExportDataToUTF8;
    global $citeStyle;
    global $citeOrder;
    global $query;
    // Individual records are objects and collections of records are strings
    $atomCollectionDoc = new XMLDocument();
    if ($convertExportDataToUTF8 == "yes" and $contentTypeCharset != "UTF-8") {
        $atomCollectionDoc->setEncoding("UTF-8");
    } else {
        $atomCollectionDoc->setEncoding($contentTypeCharset);
    }
    // Generate the basic OpenSearch Atom XML tree required for a query response:
    $atomCollection = atomGenerateBaseTags("Results");
    $showRowsOriginal = $showRows;
    // save original value of '$showRows' (which may get modified by the 'seekInMySQLResultsToOffset()' function below)
    // Find out how many rows are available and (if there were rows found) seek to the current offset:
    // function 'seekInMySQLResultsToOffset()' is defined in 'include.inc.php'
    list($result, $rowOffset, $showRows, $rowsFound, $previousOffset, $nextOffset, $showMaxRow) = seekInMySQLResultsToOffset($result, $rowOffset, $showRows, $displayType, "");
    // Setup some required variables:
    if ($rowsFound != 0 and $showRowsOriginal != 0) {
        $startIndex = $rowOffset + 1;
        // for OpenSearch, the index of the first search result is 1 while the first row number in a MySQL result set is 0, so we have to add 1
        if ($showMaxRow < $rowsFound) {
            // if we are not on the last results page
            $itemsPerPage = $showRows;
        } else {
            // last results page
            $itemsPerPage = $rowsFound - $rowOffset;
        }
        // adopt value for '$itemsPerPage' so that it equals the number of records displayed on the last page (which may be less than '$showRows')
        if ($rowsFound > $showRows) {
            // Calculate the maximum number of pages needed:
            $lastPage = $rowsFound / $showRows;
            // workaround for always rounding upward (since I don't know better! :-/):
            if (preg_match("/[0-9]+\\.[0-9+]/", $lastPage)) {
                // if the result number is not an integer
                $lastPage = (int) $lastPage + 1;
            }
            // we convert the number into an integer and add 1
            // Calculate the offset of the first record that's displayed on the last results page:
            // NOTE: Should the last offset take the current '$rowOffset' into account? I.e., take '$rowOffset' and see
            //       how many full chunks of '$showRows' can be stacked on top of it until '$rowsFound' is reached.
            //       The offset of the first of the remaining records then constitutes the '$lastOffset'.
            $lastOffset = ($lastPage - 1) * $showRows;
        } else {
            // there's only one page to be displayed
            $lastOffset = 0;
        }
    } else {
        $startIndex = 0;
        // note that "0" will currently cause an empty element to be returned (instead of the number "0"), should this be changed?
        $itemsPerPage = 0;
        $lastOffset = 0;
    }
    // Extract the 'WHERE' clause from the current SQL query:
    $queryWhereClause = extractWHEREclause($query);
    // function 'extractWHEREclause()' is defined in 'include.inc.php'
    // Setup base URL and its corresponding query parameter for formats
    // that are supported by both, 'show.php'/'rss.php' AND 'opensearch.php':
    if (!isset($_SESSION['cqlQuery'])) {
        // (while 'opensearch.php' writes the user's OpenSearch/CQL query into a session variable, this
        //  does not happen (and is not possible) if Atom XML is exported via the regular refbase GUI)
        // Generate Atom links using 'show.php' URLs (or 'rss.php' in case of RSS XML):
        $baseURL = "show.php";
        $cqlQuery = "";
        $queryParametersArray["where"] = $queryWhereClause;
    } else {
        // Generate Atom links using 'opensearch.php' URLs:
        $baseURL = "opensearch.php";
        // Extract the original OpenSearch/CQL query that was saved by 'opensearch.php' as a session variable:
        $cqlQuery = $_SESSION['cqlQuery'];
        $queryParametersArray["query"] = $cqlQuery;
        // Clear the 'cqlQuery' session variable so that subsequent calls of this function won't accidentally use an outdated OpenSearch/CQL query:
        // Note: Though we clear the session variable, the current message is still available to this script via '$cqlQuery':
        deleteSessionVariable("cqlQuery");
        // function 'deleteSessionVariable()' is defined in 'include.inc.php'
    }
    // ----------------------------------------------------------
    // Add feed-level tags:
    // - 'link' elements:
    //   NOTE: According to the Atom spec, a feed is limited to ONE 'rel=alternate' link per type and hreflang!
    //   A) Formats supported by both, 'show.php'/'rss.php' AND 'opensearch.php':
    //   - RSS feed for full query results:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "RSS XML", $queryParametersArray, true, $showRows), "alternate", "RSS XML", "Current query results as RSS feed");
    // function 'generateURL()' is defined in 'include.inc.php'
    //   - HTML output for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "html", $queryParametersArray, true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "html", "Current results page as HTML");
    //   - SRW_DC XML data for current results page:
    //     NOTE: A link to SRW_MODS XML is already used with this type!
    //		atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "SRW_DC XML", $queryParametersArray, true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "SRW_DC XML", "Current results page as SRW_DC XML data");
    //   - SRW_MODS XML data for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "SRW_MODS XML", $queryParametersArray, true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "SRW_MODS XML", "Current results page as SRW_MODS XML data");
    //   - Atom XML data for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, $rowOffset, $citeStyle, $citeOrder), "self", "Atom XML", "Current results page");
    //   - Atom XML data for first results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, 0, $citeStyle, $citeOrder), "first", "Atom XML", "First results page");
    //   - Atom XML data for previous results page:
    if ($startIndex > $showRows) {
        // if there are any previous results pages
        atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, $previousOffset, $citeStyle, $citeOrder), "previous", "Atom XML", "Previous results page");
    }
    //   - Atom XML data for next results page:
    if ($showMaxRow < $rowsFound) {
        // if we are not on the last results page
        atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, $nextOffset, $citeStyle, $citeOrder), "next", "Atom XML", "Next results page");
    }
    //   - Atom XML data for last results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, $lastOffset, $citeStyle, $citeOrder), "last", "Atom XML", "Last results page");
    //   B) Other export formats supported by 'show.php':
    //   NOTE: These export formats currently do not support paging of results via '$showRows' and '$rowOffset' and thus always export the entire result set!
    //   TODO: add links for ADS, ISI and Word XML
    //   - BibTeX data for all results:
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "BibTeX", array("where" => $queryWhereClause), true, $showRows, $rowOffset, "", $citeOrder), "alternate", "BibTeX", "All results as BibTeX data");
    //   - Endnote data for all results:
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "Endnote", array("where" => $queryWhereClause), true, $showRows, $rowOffset, "", $citeOrder), "alternate", "Endnote", "All results as Endnote data");
    //   - RIS data for all results:
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "RIS", array("where" => $queryWhereClause), true, $showRows, $rowOffset, "", $citeOrder), "alternate", "RIS", "All results as RIS data");
    //   - MODS XML data for all results:
    //     NOTE: A link to SRW_MODS XML is already used with this type!
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "MODS XML", array("where" => $queryWhereClause), true, $showRows, $rowOffset, "", $citeOrder), "alternate", "MODS XML", "All results as MODS XML data");
    //   - OAI_DC XML data for all results:
    //     NOTE: A link to SRW_MODS XML is already used with this type!
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "OAI_DC XML", array("where" => $queryWhereClause), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "OAI_DC XML", "All results as OAI_DC XML data");
    //   - ODF XML data for all results:
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "ODF XML", array("where" => $queryWhereClause, "exportType" => "file"), true, $showRows, $rowOffset, "", $citeOrder), "alternate", "ODF XML", "All results as ODF XML data");
    //   C) Citation formats supported by 'show.php':
    //   NOTE: Citation formats support paging of results via '$showRows' and '$rowOffset' if the 'client' parameter contains a value that starts with "cli"
    //   - RTF citations for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "RTF", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "RTF", "Current results page as citations in RTF format");
    //   - PDF citations for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "PDF", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "PDF", "Current results page as citations in PDF format");
    //   - LaTeX citations for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "LaTeX", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "LaTeX", "Current results page as citations in LaTeX format");
    //   - LaTeX .bbl citations for current results page:
    //     NOTE: A link to LaTeX citations is already used with this type!
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "LaTeX .bbl", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "LaTeX .bbl", "Current results page as citations in LaTeX .bbl format");
    //   - Markdown citations for current results page:
    atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "Markdown", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "Markdown", "Current results page as citations in Markdown format");
    //   - ASCII citations for current results page:
    //     (NOTE: A link to Markdown citations is already used with this type!
    //            Additionally, ASCII output with 'client=cli...' causes text output to be meant as shell response)
    //		atomLink($atomCollection, $databaseBaseURL . generateURL("show.php", "ASCII", array("where" => $queryWhereClause, "client" => "cli-refbase_atom-1.0"), true, $showRows, $rowOffset, $citeStyle, $citeOrder), "alternate", "ASCII", "Current results page as citations in ASCII format");
    // - 'id':
    //   NOTE: is this a valid feed ID?
    //   TODO: should we rather use a feed ID that conforms to the Tag URI (RFC 4151)? Spec: <http://tools.ietf.org/html/rfc4151>;
    //         or should we use an ID such as '<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>' ?
    addNewBranch($atomCollection, "id", array(), $databaseBaseURL . generateURL($baseURL, "Atom XML", $queryParametersArray, true, $showRows, $rowOffset, $citeStyle, $citeOrder));
    // function 'addNewBranch()' is defined in 'webservice.inc.php'
    // - OpenSearch elements:
    //   - 'opensearch:totalResults' contains the number of search results available for the current search:
    //      NOTE: The OpenSearch spec says: "If the totalResults element does not appear on the page then the
    //            search client should consider the current page to be the last page of search results."
    //            So does that, in turn, mean that we should better skip this element on the last results page?
    addNewBranch($atomCollection, "opensearch:totalResults", array(), $rowsFound);
    //   - 'opensearch:startIndex' contains the index of the first search result in the current set of search results:
    addNewBranch($atomCollection, "opensearch:startIndex", array(), $startIndex);
    //   - 'opensearch:itemsPerPage' contains the number of search results returned per page:
    addNewBranch($atomCollection, "opensearch:itemsPerPage", array(), $itemsPerPage);
    //   - 'opensearch:Query' defines a search query that can be performed by search clients:
    if (!empty($cqlQuery)) {
        // convert query string to UTF-8:
        // (if '$convertExportDataToUTF8' is set to "yes" in 'ini.inc.php' and character encoding is not UTF-8 already)
        if ($convertExportDataToUTF8 == "yes" and $contentTypeCharset != "UTF-8") {
            $cqlQuery = convertToCharacterEncoding("UTF-8", "IGNORE", $cqlQuery);
        }
        // function 'convertToCharacterEncoding()' is defined in 'include.inc.php'
        addNewBranch($atomCollection, "opensearch:Query", array("role" => "request", "title" => "Current query", "searchTerms" => $cqlQuery, "startIndex" => $startIndex, "count" => $itemsPerPage), "");
    }
    // ----------------------------------------------------------
    // Add Atom XML entries:
    if ($showRowsOriginal != 0) {
        // Define inline text markup to be used by the 'citeRecord()' function:
        $markupPatternsArray = array("bold-prefix" => "<b>", "bold-suffix" => "</b>", "italic-prefix" => "<i>", "italic-suffix" => "</i>", "underline-prefix" => "<u>", "underline-suffix" => "</u>", "endash" => "&#8211;", "emdash" => "&#8212;", "ampersand" => "&amp;", "double-quote" => "&quot;", "double-quote-left" => "&ldquo;", "double-quote-right" => "&rdquo;", "single-quote" => "'", "single-quote-left" => "&lsquo;", "single-quote-right" => "&rsquo;", "less-than" => "&lt;", "greater-than" => "&gt;", "newline" => "\n<br>\n");
        $exportArray = array();
        // array for individually exported records
        // Generate the export for each record and push them onto an array:
        for ($rowCounter = 0; $rowCounter < $showRows && ($row = @mysql_fetch_array($result)); $rowCounter++) {
            // Export the current record as Atom XML entry:
            $entry = atomEntry($row, $markupPatternsArray);
            if (!empty($entry)) {
                // unless the record buffer is empty...
                array_push($exportArray, $entry);
            }
            // ...add it to an array of exports
        }
        // for each of the Atom XML entries in the result set...
        foreach ($exportArray as $atom) {
            $atomCollection->addXMLasBranch($atom);
        }
    }
    $atomCollectionDoc->setXML($atomCollection);
    $atomCollectionString = $atomCollectionDoc->getXMLString();
    // Add the XML Stylesheet definition:
    // Note that this is just a hack (that should get fixed) since I don't know how to do it properly using the ActiveLink PHP XML Package ?:-/
    if (!empty($exportStylesheet)) {
        $atomCollectionString = preg_replace("/(?=\\<feed)/i", "<?xml-stylesheet type=\"text/xsl\" href=\"" . $exportStylesheet . "\"?>\n", $atomCollectionString);
    }
    // NOTE: Firefox >=2.x, Safari >=2.x and IE >=7.x break client-side XSL for RSS and Atom feeds!
    //       See e.g.: <http://decafbad.com/blog/2006/11/02/firefox-20-breaks-client-side-xsl-for-rss-and-atom-feeds>
    // TODO: Re-evaluate: This is a VERY dirty hack that prevents the feed sniffing and subsequent
    //       browser applied default XSLT stylesheet that has been implemented by FireFox 2, Safari 2
    //       and Internet Explorer 7. To prevent the feed sniffing we insert a comment before the feed
    //       element that is larger than 512 bytes. See: <http://feedme.mind-it.info/pivot/entry.php?id=9>
    if (!empty($exportStylesheet)) {
        $atomCollectionString = preg_replace("/(?=\\<feed)/i", "<!-- This is a comment that has been inserted since Internet Explorer 7, FireFox 2 and Safari 3 break client-side XSL for RSS and Atom feeds, i.e. these browsers don't honour a xml stylesheet instruction but instead apply their own default XSLT stylesheet. While this makes sense for reasons of consistency, it's very unfortunate that there's no proper option to circumvent this behaviour since it effectively prevents custom feed-based GUI solutions that were made for other purposes than the ones intended by the browser developers. Luckily the designers of these browsers use very brittle sniffing techniques that can be overridden by consuming the first 512 bytes of an XML file. This comment provides these essential 512 bytes of crud, thus preventing the feed sniffing and subsequent applied default XSLT stylesheet that has been implemented by Internet Explorer 7, FireFox 2 and Safari 2. But, unfortunately, it destroys the nice simplicity and cleanliness of this Atom feed. For more info see e.g. <http://decafbad.com/blog/2006/11/02/firefox-20-breaks-client-side-xsl-for-rss-and-atom-feeds> and <http://feedme.mind-it.info/pivot/entry.php?id=9>. -->\n", $atomCollectionString);
    }
    return $atomCollectionString;
}