Coverage Report

Created: 2026-11-12 08:28

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
4.26k
{
30
4.26k
#ifndef USE_ONLY_EMBEDDED_RESOURCE_FILES
31
4.26k
    if (osRegistryPath.empty())
32
4.26k
    {
33
4.26k
#ifdef EMBED_RESOURCE_FILES
34
4.26k
        CPLErrorStateBackuper oErrorStateBackuper(CPLQuietErrorHandler);
35
4.26k
#endif
36
4.26k
        const char *pszFilename = CPLFindFile("gdal", "gml_registry.xml");
37
4.26k
        if (pszFilename)
38
0
            osRegistryPath = pszFilename;
39
4.26k
    }
40
4.26k
#endif
41
4.26k
    CPLXMLNode *psRootNode = nullptr;
42
4.26k
    if (!osRegistryPath.empty())
43
0
    {
44
0
        psRootNode = CPLParseXMLFile(osRegistryPath);
45
0
    }
46
4.26k
#ifdef EMBED_RESOURCE_FILES
47
4.26k
    else
48
4.26k
    {
49
4.26k
        const char *pszContent = GMLGetFileContent("gml_registry.xml");
50
4.26k
        if (pszContent)
51
4.26k
        {
52
4.26k
            static const bool bOnce [[maybe_unused]] = []()
53
4.26k
            {
54
7
                CPLDebug("GML", "Using embedded gml_registry.xml");
55
7
                return true;
56
7
            }();
57
4.26k
            psRootNode = CPLParseXMLString(pszContent);
58
4.26k
        }
59
4.26k
    }
60
4.26k
#endif
61
4.26k
    if (psRootNode == nullptr)
62
0
        return false;
63
4.26k
    CPLXMLNode *psRegistryNode = CPLGetXMLNode(psRootNode, "=gml_registry");
64
4.26k
    if (psRegistryNode == nullptr)
65
0
    {
66
0
        CPLDestroyXMLNode(psRootNode);
67
0
        return false;
68
0
    }
69
4.26k
    CPLXMLNode *psIter = psRegistryNode->psChild;
70
51.1k
    while (psIter != nullptr)
71
46.8k
    {
72
46.8k
        if (psIter->eType == CXT_Element &&
73
25.5k
            strcmp(psIter->pszValue, "namespace") == 0)
74
25.5k
        {
75
25.5k
            GMLRegistryNamespace oNameSpace;
76
25.5k
            if (oNameSpace.Parse(osRegistryPath, psIter))
77
25.5k
            {
78
25.5k
                aoNamespaces.push_back(std::move(oNameSpace));
79
25.5k
            }
80
25.5k
        }
81
46.8k
        psIter = psIter->psNext;
82
46.8k
    }
83
4.26k
    CPLDestroyXMLNode(psRootNode);
84
4.26k
    return true;
85
4.26k
}
86
87
/************************************************************************/
88
/*                               Parse()                                */
89
/************************************************************************/
90
91
bool GMLRegistryNamespace::Parse(const char *pszRegistryFilename,
92
                                 CPLXMLNode *psNode)
93
25.5k
{
94
25.5k
    const char *pszPrefix = CPLGetXMLValue(psNode, "prefix", "");
95
25.5k
    const char *pszURI = CPLGetXMLValue(psNode, "uri", nullptr);
96
25.5k
    if (pszURI == nullptr)
97
0
        return false;
98
25.5k
    osPrefix = pszPrefix;
99
25.5k
    osURI = pszURI;
100
25.5k
    const char *pszUseGlobalSRSName =
101
25.5k
        CPLGetXMLValue(psNode, "useGlobalSRSName", nullptr);
102
25.5k
    if (pszUseGlobalSRSName != nullptr &&
103
21.3k
        strcmp(pszUseGlobalSRSName, "true") == 0)
104
21.3k
        bUseGlobalSRSName = true;
105
106
25.5k
    CPLXMLNode *psIter = psNode->psChild;
107
276k
    while (psIter != nullptr)
108
251k
    {
109
251k
        if (psIter->eType == CXT_Element &&
110
183k
            strcmp(psIter->pszValue, "featureType") == 0)
111
183k
        {
112
183k
            GMLRegistryFeatureType oFeatureType;
113
183k
            if (oFeatureType.Parse(pszRegistryFilename, psIter))
114
183k
            {
115
183k
                aoFeatureTypes.push_back(std::move(oFeatureType));
116
183k
            }
117
183k
        }
118
251k
        psIter = psIter->psNext;
119
251k
    }
120
25.5k
    return true;
121
25.5k
}
122
123
/************************************************************************/
124
/*                               Parse()                                */
125
/************************************************************************/
126
127
bool GMLRegistryFeatureType::Parse(const char *pszRegistryFilename,
128
                                   CPLXMLNode *psNode)
129
183k
{
130
183k
    const char *pszElementName = CPLGetXMLValue(psNode, "elementName", nullptr);
131
183k
    osSchemaLocation = CPLGetXMLValue(psNode, "schemaLocation", "");
132
183k
    osGFSSchemaLocation = CPLGetXMLValue(psNode, "gfsSchemaLocation", "");
133
183k
    if (pszElementName == nullptr ||
134
183k
        (osSchemaLocation.empty() && osGFSSchemaLocation.empty()))
135
0
        return false;
136
137
183k
    const char *pszElementValue =
138
183k
        CPLGetXMLValue(psNode, "elementValue", nullptr);
139
183k
    osElementName = pszElementName;
140
141
183k
    if (!osSchemaLocation.empty())
142
17.0k
    {
143
17.0k
        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
17.0k
    }
153
166k
    else if (!osGFSSchemaLocation.empty())
154
166k
    {
155
166k
        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
166k
    }
165
166
183k
    if (pszElementValue != nullptr)
167
17.0k
    {
168
17.0k
        osElementValue = pszElementValue;
169
17.0k
    }
170
171
183k
    return true;
172
183k
}