From cb7a13940827ca9d4dcc41d505ea1a144cb9a914 Mon Sep 17 00:00:00 2001 From: Christoph Reiter Date: Mon, 4 Nov 2024 11:43:25 +0100 Subject: [PATCH] Fix parsing of QueryResult responses after recent API changes Starting some days ago Alma added a namespace to the "rowset" tag in the QueryResult response. Adjust our xpath to ignore namespaces there to work with the old and the new format, and move the parsing in a central place. This fixes all APIs using the analytics API internally to return empty responses. --- src/Service/AlmaApi.php | 12 ++++++------ src/Service/AlmaUtils.php | 11 +++++++++++ tests/AlmaUtilsTest.php | 28 ++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/Service/AlmaApi.php b/src/Service/AlmaApi.php index 7010752..b5f64f9 100644 --- a/src/Service/AlmaApi.php +++ b/src/Service/AlmaApi.php @@ -850,7 +850,7 @@ public function addAllBookLoansByLibraryToCollection(Sublibrary $library, ArrayC $resumptionData['token'] ??= (string) $xml->ResumptionToken; $isFinished = ((string) $xml->IsFinished) !== 'false'; - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); /** @var \SimpleXMLElement $row */ foreach ($rows as $row) { @@ -1425,7 +1425,7 @@ public function getBudgetMonetaryAmountsByLibrary(Sublibrary $library): array $mapping = AlmaUtils::getColumnMapping($xml); $libraryCode = $library->getCode(); $fundLedgerCode = $libraryCode.'MON'; - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); if (count($rows) === 0) { return []; @@ -1549,7 +1549,7 @@ public function addAllBookOffersByLibraryToCollection(Sublibrary $library, Array $resumptionData['token'] ??= (string) $xml->ResumptionToken; $isFinished = ((string) $xml->IsFinished) !== 'false'; - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); /** @var \SimpleXMLElement $row */ foreach ($rows as $row) { @@ -1691,7 +1691,7 @@ public function addAllBookOrdersByLibraryToCollection(Sublibrary $library, Array $resumptionData['token'] ??= (string) $xml->ResumptionToken; $isFinished = ((string) $xml->IsFinished) !== 'false'; - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); // FIXME: We get duplicated entries where Invoice Line-Currency/Invoice-Currency/Invoice Line Total Price // are missing. Since we don't use them right now just ignore those duplicates. @@ -1802,7 +1802,7 @@ private function getAnalyticsUpdatesHash() return $this->getFallbackAnalyticsUpdatesHash(); } - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); if (count($rows) === 0) { return $this->getFallbackAnalyticsUpdatesHash(); @@ -1827,7 +1827,7 @@ public function getAnalyticsUpdatesData() return null; } - $rows = $xml->xpath('ResultXml/rowset/Row'); + $rows = AlmaUtils::getRows($xml); if (count($rows) === 0) { return null; diff --git a/src/Service/AlmaUtils.php b/src/Service/AlmaUtils.php index 8354b4e..3313ca8 100644 --- a/src/Service/AlmaUtils.php +++ b/src/Service/AlmaUtils.php @@ -48,4 +48,15 @@ public static function mapRowColumns(\SimpleXMLElement $row, array $mapping): ar return $values; } + + public static function getRows(\SimpleXMLElement $queryResult): array + { + // Around 2024-11 they added namespaces to rowset, so match by tag name only to support both versions + $res = $queryResult->xpath('ResultXml//*[local-name()="Row"]'); + if ($res === null || $res === false) { + throw new \RuntimeException('Broken Alma response'); + } + + return $res; + } } diff --git a/tests/AlmaUtilsTest.php b/tests/AlmaUtilsTest.php index d1862c7..16568ad 100644 --- a/tests/AlmaUtilsTest.php +++ b/tests/AlmaUtilsTest.php @@ -44,4 +44,32 @@ public function testGetColumnMapping() $this->assertEquals($mapped['::0'], ''); $this->assertEquals($mapped['Bibliographic Details::Author'], 'Zwerger, Klaus'); } + + public function testGetRows() + { + $data = ' + foobar + true + + + + 0 + Something + F00042FOR + Test + 1 + 0 + 1 + 1 + 0 + + + +'; + + $xml = simplexml_load_string($data); + $rows = AlmaUtils::getRows($xml); + $this->assertCount(1, $rows); + $this->assertSame('Test', (string) $rows[0]->Column3); + } }