diff --git a/src/KmlParser.php b/src/KmlParser.php index c899dd1..67c092b 100755 --- a/src/KmlParser.php +++ b/src/KmlParser.php @@ -60,7 +60,7 @@ public function loadFromString(string $content): self $this->xml->registerXPathNamespace('kml', $this->namespace); return $this; - } catch (\Exception $e) { + } catch (Exception $e) { libxml_clear_errors(); throw KmlParserException::failedToParse($e->getMessage()); } @@ -95,7 +95,7 @@ public function getPlacemarks(): array foreach ($placemarksXml as $placemarkXml) { $placemark = [ - 'name' => (string) ($placemarkXml->name ?: $placemarkXml->n), + 'name' => (string) $placemarkXml->name, 'description' => (string) $placemarkXml->description, ]; @@ -157,6 +157,17 @@ public function getStyles(): array foreach ($stylesXml as $styleXml) { $id = (string) $styleXml->attributes()->id; + + /* + * A Style declared inline on a Placemark carries no id and cannot be + * referenced through a styleUrl. Keeping it here would make every + * anonymous style collide under the same empty key, so only shared + * styles end up in the returned map. + */ + if ($id === '') { + continue; + } + $style = [ 'id' => $id, ]; @@ -341,8 +352,6 @@ public function getDocumentName(): ?string $document = $this->xml->xpath('//kml:Document'); if (! empty($document) && isset($document[0]->name)) { return (string) $document[0]->name; - } elseif (! empty($document) && isset($document[0]->n)) { - return (string) $document[0]->n; } return null; diff --git a/tests/StyleAndNameExtractionTest.php b/tests/StyleAndNameExtractionTest.php new file mode 100644 index 0000000..038f1c4 --- /dev/null +++ b/tests/StyleAndNameExtractionTest.php @@ -0,0 +1,69 @@ + + + + 0 + + + + 0 + + + 7.7300965,45.8635629,0 + + + + Second + + + 8.1,45.1,0 + + + + +XML; +} + +beforeEach(function () { + $this->parser = (new KmlParser)->loadFromString(kmlWithStyles()); +}); + +it('reads the placemark name from the name element', function () { + expect($this->parser->getPlacemarks()[0]['name'])->toBe('0'); +}); + +it('reads the document name from the name element', function () { + expect($this->parser->getDocumentName())->toBe('0'); +}); + +it('returns only styles that can be referenced by a styleUrl', function () { + $styles = $this->parser->getStyles(); + + expect($styles)->toHaveCount(2) + ->and($styles)->toHaveKeys(['shared-red', 'shared-blue']) + ->and($styles)->not->toHaveKey('') + ->and($styles['shared-red']['iconStyle']['scale'])->toBe(1.2) + ->and($styles['shared-blue']['iconStyle']['scale'])->toBe(0.8); +});