LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/kml - kmlvector.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 79 87 90.8 %
Date: 2026-06-27 16:33:51 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  KML Driver
       4             :  * Purpose:  Specialization of the kml class, only for vectors in kml files.
       5             :  * Author:   Jens Oberender, j.obi@troja.net
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2007, Jens Oberender
       9             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "kmlvector.h"
      16             : 
      17             : #include <string>
      18             : 
      19             : #include "cpl_conv.h"
      20             : #include "cpl_error.h"
      21             : // #include "kmlnode.h"
      22             : #include "kmlutility.h"
      23             : 
      24        5675 : bool KMLVector::isLeaf(std::string const &sIn) const
      25             : {
      26       15851 :     return sIn.compare("name") == 0 || sIn.compare("coordinates") == 0 ||
      27       15851 :            sIn.compare("altitudeMode") == 0 || sIn.compare("description") == 0;
      28             : }
      29             : 
      30             : // Container - FeatureContainer - Feature
      31             : 
      32        5994 : bool KMLVector::isContainer(std::string const &sIn) const
      33             : {
      34       11577 :     return sIn.compare("Folder") == 0 || sIn.compare("Document") == 0 ||
      35       11577 :            sIn.compare("kml") == 0;
      36             : }
      37             : 
      38        6130 : bool KMLVector::isFeatureContainer(std::string const &sIn) const
      39             : {
      40       12249 :     return sIn.compare("MultiGeometry") == 0 ||
      41        6119 :            sIn.compare("MultiPolygon") == 0        // non conformant
      42        6118 :            || sIn.compare("MultiLineString") == 0  // non conformant
      43        6117 :            || sIn.compare("MultiPoint") == 0       // non conformant
      44       12249 :            || sIn.compare("Placemark") == 0;
      45             : }
      46             : 
      47        4756 : bool KMLVector::isFeature(std::string const &sIn) const
      48             : {
      49        9275 :     return sIn.compare("Polygon") == 0 || sIn.compare("LineString") == 0 ||
      50        9275 :            sIn.compare("Point") == 0;
      51             : }
      52             : 
      53        5726 : bool KMLVector::isRest(std::string const &sIn) const
      54             : {
      55       11228 :     return sIn.compare("outerBoundaryIs") == 0 ||
      56       11228 :            sIn.compare("innerBoundaryIs") == 0 ||
      57       11192 :            sIn.compare("LinearRing") == 0;
      58             : }
      59             : 
      60         147 : void KMLVector::findLayers(KMLNode *poNode, int bKeepEmptyContainers)
      61             : {
      62         147 :     bool bEmpty = true;
      63             : 
      64             :     // Start with the trunk
      65         147 :     if (nullptr == poNode)
      66             :     {
      67          24 :         nNumLayers_ = 0;
      68          24 :         poNode = poTrunk_;
      69             :     }
      70             : 
      71         294 :     if (isFeature(poNode->getName()) || isFeatureContainer(poNode->getName()) ||
      72         147 :         (isRest(poNode->getName()) && poNode->getName().compare("kml") != 0))
      73             :     {
      74           0 :         return;
      75             :     }
      76         147 :     else if (isContainer(poNode->getName()))
      77             :     {
      78         738 :         for (std::size_t z = 0; z < poNode->countChildren(); z++)
      79             :         {
      80         591 :             if (isContainer(poNode->getChild(z)->getName()))
      81             :             {
      82         123 :                 findLayers(poNode->getChild(z), bKeepEmptyContainers);
      83             :             }
      84         468 :             else if (isFeatureContainer(poNode->getChild(z)->getName()))
      85             :             {
      86         254 :                 bEmpty = false;
      87             :             }
      88             :         }
      89             : 
      90         147 :         if (bKeepEmptyContainers && poNode->getName() == "Folder")
      91             :         {
      92           6 :             if (!bEmpty)
      93           3 :                 poNode->eliminateEmpty(this);
      94             :         }
      95         141 :         else if (bEmpty)
      96             :         {
      97          63 :             return;
      98             :         }
      99             : 
     100          84 :         Nodetype nodeType = poNode->getType();
     101         162 :         if (bKeepEmptyContainers || isFeature(Nodetype2String(nodeType)) ||
     102           3 :             nodeType == Mixed || nodeType == MultiGeometry ||
     103         162 :             nodeType == MultiPoint || nodeType == MultiLineString ||
     104           0 :             nodeType == MultiPolygon)
     105             :         {
     106          84 :             poNode->setLayerNumber(nNumLayers_++);
     107          84 :             papoLayers_ = static_cast<KMLNode **>(
     108          84 :                 CPLRealloc(papoLayers_, nNumLayers_ * sizeof(KMLNode *)));
     109          84 :             papoLayers_[nNumLayers_ - 1] = poNode;
     110             :         }
     111             :         else
     112             :         {
     113           0 :             CPLDebug("KML", "We have a strange type here for node %s: %s",
     114           0 :                      poNode->getName().c_str(),
     115           0 :                      Nodetype2String(poNode->getType()).c_str());
     116             :         }
     117             :     }
     118             :     else
     119             :     {
     120           0 :         CPLDebug("KML",
     121             :                  "There is something wrong!  Define KML_DEBUG to see details");
     122           0 :         if (CPLGetConfigOption("KML_DEBUG", nullptr) != nullptr)
     123           0 :             print();
     124             :     }
     125             : }
     126             : 
     127        1892 : void KMLVector::findSchemas(KMLNode *poNode)
     128             : {
     129        1892 :     if (nullptr == poNode)
     130             :     {
     131          24 :         poNode = poTrunk_;
     132             :     }
     133        1892 :     if (poNode->getType() == Schema)
     134             :     {
     135           2 :         std::string osSchemaId;
     136           3 :         for (const auto *poAttr : poNode->getAttributes())
     137             :         {
     138           2 :             if (poAttr->sName == "id")
     139           1 :                 osSchemaId = poAttr->sValue;
     140             :         }
     141           1 :         if (!osSchemaId.empty())
     142             :         {
     143           2 :             std::vector<std::unique_ptr<OGRFieldDefn>> fields;
     144             : 
     145           4 :             for (std::size_t z = 0; z < poNode->countChildren(); z++)
     146             :             {
     147           3 :                 auto poChild = poNode->getChild(z);
     148           3 :                 if (poChild->getType() == SimpleField)
     149             :                 {
     150           6 :                     std::string osAttrName;
     151           6 :                     std::string osAttrType;
     152           9 :                     for (const auto *poAttr : poChild->getAttributes())
     153             :                     {
     154           6 :                         if (poAttr->sName == "name")
     155           3 :                             osAttrName = poAttr->sValue;
     156           3 :                         else if (poAttr->sName == "type")
     157           3 :                             osAttrType = poAttr->sValue;
     158             :                     }
     159           3 :                     if (!osAttrName.empty() && !osAttrType.empty())
     160             :                     {
     161           3 :                         if (osAttrType == "string")
     162           1 :                             fields.push_back(std::make_unique<OGRFieldDefn>(
     163           2 :                                 osAttrName.c_str(), OFTString));
     164           2 :                         else if (osAttrType == "float")
     165           1 :                             fields.push_back(std::make_unique<OGRFieldDefn>(
     166           2 :                                 osAttrName.c_str(), OFTReal));
     167           1 :                         else if (osAttrType == "int")
     168           1 :                             fields.push_back(std::make_unique<OGRFieldDefn>(
     169           2 :                                 osAttrName.c_str(), OFTInteger));
     170             :                     }
     171             :                 }
     172             :             }
     173             : 
     174           1 :             oMapSchemas_[osSchemaId] = std::move(fields);
     175             :         }
     176             :     }
     177             :     else
     178             :     {
     179        3759 :         for (std::size_t z = 0; z < poNode->countChildren(); z++)
     180             :         {
     181        1868 :             findSchemas(poNode->getChild(z));
     182             :         }
     183             :     }
     184        1892 : }

Generated by: LCOV version 1.14