mirror of
https://github.com/GSA/notifications-api.git
synced 2026-01-30 14:31:57 -05:00
Validate CAP against the spec
This gives us some extra confidence that there aren’t any problems with the data we’re getting from the other service. It doesn’t address any specific problems we’ve seen, rather it seems like a sensible precaution to take.
This commit is contained in:
218
app/xml_schemas/CAP-v1.2.xsd
Normal file
218
app/xml_schemas/CAP-v1.2.xsd
Normal file
@@ -0,0 +1,218 @@
|
||||
<?xml version = "1.0" encoding = "UTF-8"?>
|
||||
<!-- Copyright OASIS Open 2010 All Rights Reserved -->
|
||||
<schema xmlns = "http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace = "urn:oasis:names:tc:emergency:cap:1.2"
|
||||
xmlns:cap = "urn:oasis:names:tc:emergency:cap:1.2"
|
||||
xmlns:xs = "http://www.w3.org/2001/XMLSchema"
|
||||
elementFormDefault = "qualified"
|
||||
attributeFormDefault = "unqualified"
|
||||
version = "1.2">
|
||||
<element name = "alert">
|
||||
<annotation>
|
||||
<documentation>CAP Alert Message (version 1.2)</documentation>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "identifier" type = "xs:string"/>
|
||||
<element name = "sender" type = "xs:string"/>
|
||||
<element name = "sent">
|
||||
<simpleType>
|
||||
<restriction base = "xs:dateTime">
|
||||
<pattern value = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[-,+]\d\d:\d\d"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "status">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Actual"/>
|
||||
<enumeration value = "Exercise"/>
|
||||
<enumeration value = "System"/>
|
||||
<enumeration value = "Test"/>
|
||||
<enumeration value = "Draft"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "msgType">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Alert"/>
|
||||
<enumeration value = "Update"/>
|
||||
<enumeration value = "Cancel"/>
|
||||
<enumeration value = "Ack"/>
|
||||
<enumeration value = "Error"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "source" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "scope">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Public"/>
|
||||
<enumeration value = "Restricted"/>
|
||||
<enumeration value = "Private"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "restriction" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "addresses" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "code" type = "xs:string" minOccurs = "0" maxOccurs = "unbounded"/>
|
||||
<element name = "note" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "references" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "incidents" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "info" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "language" type = "xs:language" default = "en-US" minOccurs = "0"/>
|
||||
<element name = "category" maxOccurs = "unbounded">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Geo"/>
|
||||
<enumeration value = "Met"/>
|
||||
<enumeration value = "Safety"/>
|
||||
<enumeration value = "Security"/>
|
||||
<enumeration value = "Rescue"/>
|
||||
<enumeration value = "Fire"/>
|
||||
<enumeration value = "Health"/>
|
||||
<enumeration value = "Env"/>
|
||||
<enumeration value = "Transport"/>
|
||||
<enumeration value = "Infra"/>
|
||||
<enumeration value = "CBRNE"/>
|
||||
<enumeration value = "Other"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "event" type = "xs:string"/>
|
||||
<element name = "responseType" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Shelter"/>
|
||||
<enumeration value = "Evacuate"/>
|
||||
<enumeration value = "Prepare"/>
|
||||
<enumeration value = "Execute"/>
|
||||
<enumeration value = "Avoid"/>
|
||||
<enumeration value = "Monitor"/>
|
||||
<enumeration value = "Assess"/>
|
||||
<enumeration value = "AllClear"/>
|
||||
<enumeration value = "None"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "urgency">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Immediate"/>
|
||||
<enumeration value = "Expected"/>
|
||||
<enumeration value = "Future"/>
|
||||
<enumeration value = "Past"/>
|
||||
<enumeration value = "Unknown"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "severity">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Extreme"/>
|
||||
<enumeration value = "Severe"/>
|
||||
<enumeration value = "Moderate"/>
|
||||
<enumeration value = "Minor"/>
|
||||
<enumeration value = "Unknown"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "certainty">
|
||||
<simpleType>
|
||||
<restriction base = "xs:string">
|
||||
<enumeration value = "Observed"/>
|
||||
<enumeration value = "Likely"/>
|
||||
<enumeration value = "Possible"/>
|
||||
<enumeration value = "Unlikely"/>
|
||||
<enumeration value = "Unknown"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "audience" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "eventCode" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref = "cap:valueName"/>
|
||||
<element ref = "cap:value"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name = "effective" minOccurs = "0">
|
||||
<simpleType>
|
||||
<restriction base = "xs:dateTime">
|
||||
<pattern value = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[-,+]\d\d:\d\d"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "onset" minOccurs = "0">
|
||||
<simpleType>
|
||||
<restriction base = "xs:dateTime">
|
||||
<pattern value = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[-,+]\d\d:\d\d"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "expires" minOccurs = "0">
|
||||
<simpleType>
|
||||
<restriction base = "xs:dateTime">
|
||||
<pattern value = "\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d[-,+]\d\d:\d\d"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
</element>
|
||||
<element name = "senderName" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "headline" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "description" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "instruction" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "web" type = "xs:anyURI" minOccurs = "0"/>
|
||||
<element name = "contact" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "parameter" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref = "cap:valueName"/>
|
||||
<element ref = "cap:value"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name = "resource" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "resourceDesc" type = "xs:string"/>
|
||||
<element name = "mimeType" type = "xs:string"/>
|
||||
<element name = "size" type = "xs:integer" minOccurs = "0"/>
|
||||
<element name = "uri" type = "xs:anyURI" minOccurs = "0"/>
|
||||
<element name = "derefUri" type = "xs:string" minOccurs = "0"/>
|
||||
<element name = "digest" type = "xs:string" minOccurs = "0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name = "area" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element name = "areaDesc" type = "xs:string"/>
|
||||
<element name = "polygon" type = "xs:string" minOccurs = "0" maxOccurs = "unbounded"/>
|
||||
<element name = "circle" type = "xs:string" minOccurs = "0" maxOccurs = "unbounded"/>
|
||||
<element name = "geocode" minOccurs = "0" maxOccurs = "unbounded">
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref = "cap:valueName"/>
|
||||
<element ref = "cap:value"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name = "altitude" type = "xs:decimal" minOccurs = "0"/>
|
||||
<element name = "ceiling" type = "xs:decimal" minOccurs = "0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<any minOccurs = "0" maxOccurs = "unbounded" namespace = "http://www.w3.org/2000/09/xmldsig#" processContents = "lax"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
<element name = "valueName" type = "xs:string"/>
|
||||
<element name = "value" type = "xs:string"/>
|
||||
</schema>
|
||||
19
app/xml_schemas/__init__.py
Normal file
19
app/xml_schemas/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from lxml import etree
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def validate_xml(document, schema_file_name):
|
||||
|
||||
path = Path(__file__).resolve().parent / schema_file_name
|
||||
contents = path.read_text()
|
||||
|
||||
schema_root = etree.XML(contents.encode('utf-8'))
|
||||
schema = etree.XMLSchema(schema_root)
|
||||
parser = etree.XMLParser(schema=schema)
|
||||
|
||||
try:
|
||||
etree.fromstring(document, parser)
|
||||
except etree.XMLSyntaxError:
|
||||
return False
|
||||
|
||||
return True
|
||||
Reference in New Issue
Block a user