Coverage Report

Created: 2025-12-03 08:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/gml/gmlregistry.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GML registry
4
 * Purpose:  GML reader
5
 * Author:   Even Rouault, <even dot rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 2013, Even Rouault <even dot rouault at spatialys.com>
9
 *
10
 * SPDX-License-Identifier: MIT
11
 ****************************************************************************/
12
13
#include "cpl_port.h"
14
#include "gmlregistry.h"
15
16
#include <cstring>
17
18
#include "cpl_conv.h"
19
20
#ifdef EMBED_RESOURCE_FILES
21
#include "embedded_resources.h"
22
#endif
23
24
/************************************************************************/
25
/*                           Parse()                                    */
26
/************************************************************************/
27
28
bool GMLRegistry::Parse()
29
2.68k
{
30
2.68k
#ifndef USE_ONLY_EMBEDDED_RESOURCE_FILES
31
2.68k
    if (osRegistryPath.empty())
32
2.68k
    {
33
2.68k
#ifdef EMBED_RESOURCE_FILES
34
2.68k
        CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
35
2.68k
#endif
36
2.68k
        const char *pszFilename = CPLFindFile("gdal", "gml_registry.xml");
37
2.68k
        if (pszFilename)
38
0
            osRegistryPath = pszFilename;
39
2.68k
    }
40
2.68k
#endif
41
2.68k
    CPLXMLNode *psRootNode = nullptr;
42
2.68k
    if (!osRegistryPath.empty())
43
0
    {
44
0
        psRootNode = CPLParseXMLFile(osRegistryPath);
45
0
    }
46
2.68k
#ifdef EMBED_RESOURCE_FILES
47
2.68k
    else
48
2.68k
    {
49
2.68k
        const char *pszContent = GMLGetFileContent("gml_registry.xml");
50
2.68k
        if (pszContent)
51
2.68k
        {
52
2.68k
            static const bool bOnce [[maybe_unused]] = []()
53
2.68k
            {
54
6
                CPLDebug("GML", "Using embedded gml_registry.xml");
55
6
                return true;
56
6
            }();
57
2.68k
            psRootNode = CPLParseXMLString(pszContent);
58
2.68k
        }
59
2.68k
    }
60
2.68k
#endif
61
2.68k
    if (psRootNode == nullptr)
62
0
        return false;
63
2.68k
    CPLXMLNode *psRegistryNode = CPLGetXMLNode(psRootNode, "=gml_registry");
64
2.68k
    if (psRegistryNode == nullptr)
65
0
    {
66
0
        CPLDestroyXMLNode(psRootNode);
67
0
        return false;
68
0
    }
69
2.68k
    CPLXMLNode *psIter = psRegistryNode->psChild;
70
32.1k
    while (psIter != nullptr)
71
29.5k
    {
72
29.5k
        if (psIter->eType == CXT_Element &&
73
16.0k
            strcmp(psIter->pszValue, "namespace") == 0)
74
16.0k
        {
75
16.0k
            GMLRegistryNamespace oNameSpace;
76
16.0k
            if (oNameSpace.Parse(osRegistryPath, psIter))
77
16.0k
            {
78
16.0k
                aoNamespaces.push_back(std::move(oNameSpace));
79
16.0k
            }
80
16.0k
        }
81
29.5k
        psIter = psIter->psNext;
82
29.5k
    }
83
2.68k
    CPLDestroyXMLNode(psRootNode);
84
2.68k
    return true;
85
2.68k
}
86
87
/************************************************************************/
88
/*                           Parse()                                    */
89
/************************************************************************/
90
91
bool GMLRegistryNamespace::Parse(const char *pszRegistryFilename,
92
                                 CPLXMLNode *psNode)
93
16.0k
{
94
16.0k
    const char *pszPrefix = CPLGetXMLValue(psNode, "prefix", "");
95
16.0k
    const char *pszURI = CPLGetXMLValue(psNode, "uri", nullptr);
96
16.0k
    if (pszURI == nullptr)
97
0
        return false;
98
16.0k
    osPrefix = pszPrefix;
99
16.0k
    osURI = pszURI;
100
16.0k
    const char *pszUseGlobalSRSName =
101
16.0k
        CPLGetXMLValue(psNode, "useGlobalSRSName", nullptr);
102
16.0k
    if (pszUseGlobalSRSName != nullptr &&
103
13.4k
        strcmp(pszUseGlobalSRSName, "true") == 0)
104
13.4k
        bUseGlobalSRSName = true;
105
106
16.0k
    CPLXMLNode *psIter = psNode->psChild;
107
174k
    while (psIter != nullptr)
108
158k
    {
109
158k
        if (psIter->eType == CXT_Element &&
110
115k
            strcmp(psIter->pszValue, "featureType") == 0)
111
115k
        {
112
115k
            GMLRegistryFeatureType oFeatureType;
113
115k
            if (oFeatureType.Parse(pszRegistryFilename, psIter))
114
115k
            {
115
115k
                aoFeatureTypes.push_back(std::move(oFeatureType));
116
115k
            }
117
115k
        }
118
158k
        psIter = psIter->psNext;
119
158k
    }
120
16.0k
    return true;
121
16.0k
}
122
123
/************************************************************************/
124
/*                           Parse()                                    */
125
/************************************************************************/
126
127
bool GMLRegistryFeatureType::Parse(const char *pszRegistryFilename,
128
                                   CPLXMLNode *psNode)
129
115k
{
130
115k
    const char *pszElementName = CPLGetXMLValue(psNode, "elementName", nullptr);
131
115k
    osSchemaLocation = CPLGetXMLValue(psNode, "schemaLocation", "");
132
115k
    osGFSSchemaLocation = CPLGetXMLValue(psNode, "gfsSchemaLocation", "");
133
115k
    if (pszElementName == nullptr ||
134
115k
        (osSchemaLocation.empty() && osGFSSchemaLocation.empty()))
135
0
        return false;
136
137
115k
    const char *pszElementValue =
138
115k
        CPLGetXMLValue(psNode, "elementValue", nullptr);
139
115k
    osElementName = pszElementName;
140
141
115k
    if (!osSchemaLocation.empty())
142
10.7k
    {
143
10.7k
        if (pszRegistryFilename[0] &&
144
0
            !STARTS_WITH(osSchemaLocation.c_str(), "http://") &&
145
0
            !STARTS_WITH(osSchemaLocation.c_str(), "https://") &&
146
0
            CPLIsFilenameRelative(osSchemaLocation.c_str()))
147
0
        {
148
0
            osSchemaLocation =
149
0
                CPLFormFilenameSafe(CPLGetPathSafe(pszRegistryFilename).c_str(),
150
0
                                    osSchemaLocation.c_str(), nullptr);
151
0
        }
152
10.7k
    }
153
104k
    else if (!osGFSSchemaLocation.empty())
154
104k
    {
155
104k
        if (pszRegistryFilename[0] &&
156
0
            !STARTS_WITH(osGFSSchemaLocation.c_str(), "http://") &&
157
0
            !STARTS_WITH(osGFSSchemaLocation.c_str(), "https://") &&
158
0
            CPLIsFilenameRelative(osGFSSchemaLocation.c_str()))
159
0
        {
160
0
            osGFSSchemaLocation =
161
0
                CPLFormFilenameSafe(CPLGetPathSafe(pszRegistryFilename).c_str(),
162
0
                                    osGFSSchemaLocation.c_str(), nullptr);
163
0
        }
164
104k
    }
165
166
115k
    if (pszElementValue != nullptr)
167
10.7k
    {
168
10.7k
        osElementValue = pszElementValue;
169
10.7k
    }
170
171
115k
    return true;
172
115k
}