Errores frecuentes al validar un GML de construcciones en la SEC (y cómo arreglarlos)
Los 9 errores que más rebotes generan al subir un GML de edificios al modelo 902: encoding UTF-8, srsName en URL, exterior CCW, gml:id sin prefijo. Con XML real y la solución exacta.
La Sede Electrónica del Catastro rebota un GML de construcciones con un mensaje genérico tipo "validación negativa" o "el fichero presentado no es conforme al esquema", y nunca te dice cuál de los criterios fallaste. Para alguien que presenta el modelo 902 por primera vez, este sistema de errores opacos es desesperante.
Tras revisar varios cientos de validaciones rebotadas, los nueve errores que más rebotes generan se repiten siempre. En este artículo los tienes ordenados por frecuencia, con el XML que falla y el XML que pasa.
Si quieres el contexto completo (qué es bu-ext2d 2.0, cuándo se usa, cómo se estructura), tienes la guía completa del GML de construcciones — este artículo asume que ya conoces el formato y solo busca diagnosticar fallos.
1. Encoding UTF-8 en lugar de ISO-8859-1
Es el rebote número uno y el más confuso porque el GML de parcelas sí va en UTF-8. La gente reutiliza pipelines y se queda con el encoding equivocado.
Mal:
<?xml version="1.0" encoding="UTF-8"?>
<gml:FeatureCollection ...>
Bien:
<?xml version="1.0" encoding="ISO-8859-1"?>
<gml:FeatureCollection ...>
Y crítico: el fichero tiene que estar realmente codificado en ISO-8859-1, no solo declararlo. Si tu pipeline genera bytes UTF-8 pero declara ISO-8859-1 en la cabecera, los caracteres con tilde rompen el parser. Verifica con file -i fichero.gml en Linux/Mac o con un editor que muestre el encoding real.
2. srsName en URL en lugar de URN
Otro derivado de mezclar el formato de parcelas con el de construcciones. La SEC valida los dos con reglas opuestas:
- Parcelas (CP 4.0):
srsName="http://www.opengis.net/def/crs/EPSG/0/25830"← URL - Construcciones (bu-ext2d 2.0):
srsName="urn:ogc:def:crs:EPSG::25830"← URN
Mal (formato de parcelas en un GML de construcciones):
<gml:Surface srsName="http://www.opengis.net/def/crs/EPSG/0/25830">
Bien:
<gml:Surface srsName="urn:ogc:def:crs:EPSG::25830">
Aplica a todos los srsName del fichero: en gml:Surface, en gml:Polygon (de las piscinas) y, si los tuvieras, en gml:Point.
3. Exterior CCW (sentido OGC) en lugar de CW
La OGC define como canónico el exterior antihorario (CCW). Es lo que producen shapely.orient, JTS, PostGIS y casi cualquier librería moderna. La SEC pide lo contrario.
Mal:
<gml:exterior>
<gml:LinearRing>
<gml:posList srsDimension="2">
414000.00 4477000.00
414040.00 4477000.00
414040.00 4477025.00
414000.00 4477025.00
414000.00 4477000.00
</gml:posList>
</gml:LinearRing>
</gml:exterior>
(Recorrido: SW → SE → NE → NW → SW = antihorario)
Bien (sentido SEC):
<gml:exterior>
<gml:LinearRing>
<gml:posList srsDimension="2">
414000.00 4477000.00
414000.00 4477025.00
414040.00 4477025.00
414040.00 4477000.00
414000.00 4477000.00
</gml:posList>
</gml:LinearRing>
</gml:exterior>
(Recorrido: SW → NW → NE → SE → SW = horario)
En Python:
from shapely.geometry.polygon import orient
poly_cw = orient(poly, sign=-1.0) # exterior CW, huecos CCW
4. gml:id sin prefijo ES.SDGC.BU.
Las herramientas genéricas de exportación INSPIRE ponen identificadores arbitrarios tipo building-1, feature-001, bldg.42. La SEC exige el prefijo del catálogo DGC.
Mal:
<bu-ext2d:Building gml:id="building-001">
Bien:
<bu-ext2d:Building gml:id="ES.SDGC.BU.9398516VK3799G">
Si hay varios edificios en la misma parcela, el sufijo lleva _Edificio_NN:
<bu-ext2d:Building gml:id="ES.SDGC.BU.9398516VK3799G_Edificio_01">
<bu-ext2d:Building gml:id="ES.SDGC.BU.9398516VK3799G_Edificio_02">
Y para piscinas:
<bu-ext2d:OtherConstruction gml:id="ES.SDGC.BU.9398516VK3799G_PI.1">
5. EPSG no admitido
Solo cuatro EPSG son válidos: 25829, 25830, 25831, 32628. Cualquier otro rebota antes incluso de validar la geometría. Las trampas más habituales:
- EPSG:3857 (Web Mercator) si exportas directamente desde un mapa web sin reproyectar.
- EPSG:4326 (WGS84 geográficas) si trabajas con GeoJSON estándar.
- EPSG:23030 (ED50 antiguo) en cartografía heredada de antes de 2015.
- EPSG:25828 (UTM ETRS89 huso 28N) que existe en pyproj pero no está en la lista SEC; Canarias va en 32628 (UTM WGS84).
Mal:
<gml:Surface srsName="urn:ogc:def:crs:EPSG::3857">
Bien:
<gml:Surface srsName="urn:ogc:def:crs:EPSG::25830">
Antes de exportar, reproyecta:
from pyproj import Transformer
t = Transformer.from_crs("EPSG:3857", "EPSG:25830", always_xy=True)
x_utm, y_utm = t.transform(x_3857, y_3857)
6. Coordenadas con coma decimal
Si tu locale es es_ES, algunas serializaciones convierten 414000.00 en 414000,00. El parser GML rechaza con error de tipo.
Mal:
<gml:posList srsDimension="2">
414000,00 4477000,00
414040,00 4477025,00
</gml:posList>
Bien:
<gml:posList srsDimension="2">
414000.00 4477000.00
414040.00 4477025.00
</gml:posList>
En Python siempre formatea con f"{x:.2f}" y nunca con str(x) — str() respeta el locale.
7. Anillo exterior sin cerrar
Un LinearRing tiene que tener el mismo punto al principio y al final. Si tu pipeline genera un polígono shapely cerrado pero al serializar pierdes el punto duplicado, rebota con LinearRing not closed.
Mal:
<gml:posList srsDimension="2">
414000.00 4477000.00
414000.00 4477025.00
414040.00 4477025.00
414040.00 4477000.00
</gml:posList>
Bien:
<gml:posList srsDimension="2">
414000.00 4477000.00
414000.00 4477025.00
414040.00 4477025.00
414040.00 4477000.00
414000.00 4477000.00
</gml:posList>
Con shapely, el cierre lo da list(poly.exterior.coords) automáticamente (incluye el punto duplicado). Si lo eliminas tú al deduplicar, el GML rebota.
8. Multirrecinto declarado como varios <Building>
Cuando un edificio tiene varios cuerpos disjuntos (un patio interior, dos volúmenes unidos por porche descubierto), tiene que ir como un único <Building> con varios <gml:PolygonPatch>, no como Buildings separados.
Mal:
<gml:featureMember>
<bu-ext2d:Building gml:id="ES.SDGC.BU.RC_Edificio_01">...</bu-ext2d:Building>
</gml:featureMember>
<gml:featureMember>
<bu-ext2d:Building gml:id="ES.SDGC.BU.RC_Edificio_02">...</bu-ext2d:Building>
</gml:featureMember>
(Esto declara dos edificios separados, no un edificio con dos cuerpos.)
Bien:
<gml:featureMember>
<bu-ext2d:Building gml:id="ES.SDGC.BU.RC">
<bu-ext2d:geometry>
<gml:Surface srsName="urn:ogc:def:crs:EPSG::25830">
<gml:patches>
<gml:PolygonPatch>...cuerpo 1...</gml:PolygonPatch>
<gml:PolygonPatch>...cuerpo 2...</gml:PolygonPatch>
</gml:patches>
</gml:Surface>
</bu-ext2d:geometry>
</bu-ext2d:Building>
</gml:featureMember>
Si usas multirrecinto erróneamente, la SEC procesa el modelo 902 como alta múltiple de edificios en lugar de una alta única, y la valoración catastral cambia.
9. Piscinas con conditionOfConstruction poblado
Las piscinas (OtherConstruction con openAirPool) no tienen estado de conservación según el modelo INSPIRE. Tiene que ir explícitamente nulo.
Mal:
<bu-ext2d:OtherConstruction gml:id="ES.SDGC.BU.RC_PI.1">
<bu-ext2d:conditionOfConstruction>functional</bu-ext2d:conditionOfConstruction>
<bu-ext2d:constructionNature>openAirPool</bu-ext2d:constructionNature>
...
</bu-ext2d:OtherConstruction>
Bien:
<bu-ext2d:OtherConstruction gml:id="ES.SDGC.BU.RC_PI.1">
<bu-ext2d:conditionOfConstruction xsi:nil="true" nilReason="other:unpopulated"/>
<bu-ext2d:constructionNature>openAirPool</bu-ext2d:constructionNature>
...
</bu-ext2d:OtherConstruction>
El atributo xsi:nil="true" requiere que el namespace xsi esté declarado en la raíz: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance".
Cómo evitar los nueve errores de un solo golpe
Si cada GML te requiere comprobar manualmente nueve criterios distintos, estás un mal día de mandar uno con el encoding equivocado. La forma sostenible de presentar GMLs sin rebotes es automatizar la generación con una herramienta que respete el perfil DGC al pie de la letra.
Nuestro generador online (9 €/descarga) cubre los nueve criterios por defecto (encoding ISO-8859-1, srsName URN, exterior CW, prefijo ES.SDGC.BU., EPSG admitidos, formato de coordenadas, cierre de anillos, multirrecinto correcto, piscinas con xsi:nil). Si prefieres construir el GML a mano, vuelve a la guía completa de construcciones con la receta detallada.
Y si lo que tienes es un DXF topográfico que tienes que convertir a GML INSPIRE de parcelas (no de construcciones), echa un vistazo a los errores frecuentes que rechaza la SEC al validar parcelas — son distintos pero igual de opacos.
💡 Antes de presentar, valida. Sube tu GML a nuestro validador online gratuito y comprueba en segundos si pasaría la Sede Electrónica del Catastro — te señala cada problema de formato con su solución.
¿Te ahorras estos errores con la herramienta?
El primer GML va con el trial gratuito. Si no te convence, no pagas y descargas el GML igual.