Skip to content

Commit

Permalink
VRTTI: also support setting the metadata as a XML attached to the xml…
Browse files Browse the repository at this point in the history
…:VRTTI metadata domain of a vector layer
  • Loading branch information
rouault committed Jan 11, 2024
1 parent b866593 commit 27ae3c9
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 2 deletions.
43 changes: 43 additions & 0 deletions autotest/gdrivers/vrttileindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -2553,3 +2553,46 @@ def test_vrttileindex_open_options(tmp_vsimem):
assert vrt_ds.GetGeoTransform() == pytest.approx(
(440720.0, 30.0, 0.0, 3751320.0, 0.0, -30.0)
)


def test_vrttileindex_xml_vrtti_embedded(tmp_vsimem):

index_filename = str(tmp_vsimem / "index.vrt.gpkg")

src_ds = gdal.Open(os.path.join(os.getcwd(), "data", "byte.tif"))
index_ds, lyr = create_basic_tileindex(index_filename, src_ds)

xml_content = """<VRTTileIndexDataset>
<ResX>60</ResX>
<ResY>60</ResY>
<SortField>location</SortField>
<SortFieldAsc>true</SortFieldAsc>
<Band band="1" dataType="UInt16">
<Description>my band</Description>
<Offset>2</Offset>
<Scale>3</Scale>
<NoDataValue>4</NoDataValue>
<UnitType>dn</UnitType>
<ColorInterp>Gray</ColorInterp>
<ColorTable/>
<CategoryNames><Category>cat</Category></CategoryNames>
<GDALRasterAttributeTable/>
</Band>
</VRTTileIndexDataset>"""

lyr.SetMetadata([xml_content], "xml:VRTTI")
del index_ds

vrt_ds = gdal.Open(index_filename)
band = vrt_ds.GetRasterBand(1)
assert band.GetDescription() == "my band"
assert band.DataType == gdal.GDT_UInt16
assert band.GetOffset() == 2
assert band.GetScale() == 3
assert band.GetNoDataValue() == 4
assert band.GetUnitType() == "dn"
assert band.GetColorInterpretation() == gdal.GCI_GrayIndex
assert band.GetColorTable() is not None
assert band.GetCategoryNames() == ["cat"]
assert band.GetDefaultRAT() is not None
del vrt_ds
4 changes: 3 additions & 1 deletion data/gdalvrtti.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
<xs:complexType>
<xs:sequence>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="IndexDataset" type="xs:string" minOccurs="1"/>
<!-- IndexDataset is required for a standalone XML VRTTI -->
<!-- It is ignored if the XML document is embedded in the xml:VRTTI metadata domain of a vector layer -->
<xs:element name="IndexDataset" type="xs:string"/>

<xs:element name="IndexLayer" type="xs:string"/>
<xs:element name="Filter" type="xs:string"/>
Expand Down
7 changes: 6 additions & 1 deletion doc/source/drivers/raster/vrtti.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ In addition to those layer metadata items, the dataset-level metadata item
``TILE_INDEX_LAYER`` may be set to indicate, for dataset with multiple layers,
which one should be used as the tile index layer.

Alternatively to setting those metadata items individually, the corresponding
information can be grouped together in a VRTTI XML document, attached in the
``xml:VRTTI`` metadata domain of the layer (for drivers that support alternate
metadata domains such as GeoPackage)

VRTTI XML format
----------------

Expand All @@ -236,7 +241,7 @@ mentioned in the previous section.
.. code-block:: xml
<VRTTileIndexDataset>
<IndexDataset>PG:dbname=my_db</IndexDataset> <!-- required -->
<IndexDataset>PG:dbname=my_db</IndexDataset> <!-- required for stanalone XML VRTTI files. Ignored if embedded in the xml:VRTTI metadata domain of the layer -->
<IndexLayer>my_layer</IndexLayer> <!-- optional, but required if there are multiple layers in IndexDataset -->
<Filter>pub_date >= '2023/12/01'</Filter> <!-- optional -->
<SortField>pub_date</SortField> <!-- optional -->
Expand Down
20 changes: 20 additions & 0 deletions frmts/vrt/vrttileindexdataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,26 @@ bool VRTTileIndexDataset::Open(GDALOpenInfo *poOpenInfo)
return false;
}

// Try to get the metadata from an embedded xml:VRTTI domain
if (!m_psXMLTree)
{
char **papszMD = m_poLayer->GetMetadata("xml:VRTTI");
if (papszMD && papszMD[0])
{
m_psXMLTree.reset(CPLParseXMLString(papszMD[0]));
if (m_psXMLTree == nullptr)
return false;

psRoot = CPLGetXMLNode(m_psXMLTree.get(), "=VRTTileIndexDataset");
if (psRoot == nullptr)
{
CPLError(CE_Failure, CPLE_AppDefined,
"Missing VRTTileIndexDataset root element.");
return false;
}
}
}

const auto GetOption = [poOpenInfo, psRoot, this](const char *pszItem)
{
if (psRoot)
Expand Down

0 comments on commit 27ae3c9

Please sign in to comment.