-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
86 lines (72 loc) · 2.36 KB
/
Copy pathmain.py
File metadata and controls
86 lines (72 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from fastapi import FastAPI, UploadFile, File
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from lxml import etree
from pathlib import Path
import time
app = FastAPI(title="NeTEx Validator CH", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["POST", "GET"],
allow_headers=["*"],
)
# Load XSD once at startup
XSD_PATH = Path(__file__).parent / "xsd" / "NeTEx_publication.xsd"
_schema = None
def get_schema() -> etree.XMLSchema:
global _schema
if _schema is None:
_schema = etree.XMLSchema(etree.parse(str(XSD_PATH)))
return _schema
@app.on_event("startup")
async def startup():
"""Pre-load schema at startup so first request is fast."""
try:
get_schema()
print("XSD schema loaded OK")
except Exception as e:
print(f"XSD load error: {e}")
@app.get("/health")
def health():
return {"status": "ok", "xsd": str(XSD_PATH.exists())}
@app.post("/validate")
async def validate(file: UploadFile = File(...)):
t0 = time.time()
try:
content = await file.read()
# Parse XML
try:
doc = etree.fromstring(content)
except etree.XMLSyntaxError as e:
return JSONResponse({
"valid": False,
"filename": file.filename,
"errors": [{
"line": e.lineno,
"col": e.offset,
"message": str(e.msg),
"level": "error",
}],
"duration_ms": int((time.time()-t0)*1000),
})
# Validate against XSD
schema = get_schema()
valid = schema.validate(doc)
errors = []
for e in schema.error_log:
errors.append({
"line": e.line,
"col": e.column,
"message": e.message,
"level": e.level_name.lower(), # "error" or "warning"
})
return JSONResponse({
"valid": valid,
"filename": file.filename,
"errors": errors,
"error_count": len(errors),
"duration_ms": int((time.time()-t0)*1000),
})
except Exception as e:
return JSONResponse({"valid": False, "errors": [{"message": str(e), "level": "error"}]}, status_code=500)