mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-10-02 13:04:49 +00:00
switch from dom to xmlschema
as suggested by @Moult, xmlschema better fits the purpose than xml.dom.minidom
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
import operator
|
import operator
|
||||||
import ifcopenshell.util.element
|
import ifcopenshell.util.element
|
||||||
|
|
||||||
from xml.dom.minidom import parse
|
|
||||||
from xmlschema import XMLSchema
|
from xmlschema import XMLSchema
|
||||||
|
|
||||||
|
|
||||||
@@ -53,10 +52,16 @@ class facet(metaclass=meta_facet):
|
|||||||
self.node = node
|
self.node = node
|
||||||
|
|
||||||
def __getattr__(self, k):
|
def __getattr__(self, k):
|
||||||
try:
|
|
||||||
v = self.node.getElementsByTagName(k)[0]
|
if k in self.node:
|
||||||
except IndexError:
|
v = self.node[k]
|
||||||
|
else:
|
||||||
v = None
|
v = None
|
||||||
|
|
||||||
|
return v
|
||||||
|
|
||||||
|
#TODO implement restrictons
|
||||||
|
"""
|
||||||
if v:
|
if v:
|
||||||
elems = [n for n in v.childNodes if n.nodeType == n.ELEMENT_NODE]
|
elems = [n for n in v.childNodes if n.nodeType == n.ELEMENT_NODE]
|
||||||
if elems:
|
if elems:
|
||||||
@@ -65,6 +70,7 @@ class facet(metaclass=meta_facet):
|
|||||||
return v.firstChild.nodeValue.strip()
|
return v.firstChild.nodeValue.strip()
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
"""
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for k in self.parameters:
|
for k in self.parameters:
|
||||||
@@ -90,10 +96,16 @@ class entity(facet):
|
|||||||
if self.predefinedtype and hasattr(inst, "PredefinedType"):
|
if self.predefinedtype and hasattr(inst, "PredefinedType"):
|
||||||
# logger.debug("Testing if entity predefinedtype '%s' == '%s'", inst.PredefinedType, self.predefinedtype)
|
# logger.debug("Testing if entity predefinedtype '%s' == '%s'", inst.PredefinedType, self.predefinedtype)
|
||||||
self.message = "an entity name '%(name)s' of predefined type '%(predefinedtype)s'"
|
self.message = "an entity name '%(name)s' of predefined type '%(predefinedtype)s'"
|
||||||
return facet_evaluation(inst.is_a(self.name) and inst.PredefinedType == self.predefinedtype, self.message % {"name": inst.is_a(), "predefinedtype": inst.PredefinedType})
|
return facet_evaluation(
|
||||||
|
inst.is_a(self.name) and inst.PredefinedType == self.predefinedtype,
|
||||||
|
self.message % {"name": inst.is_a(), "predefinedtype": inst.PredefinedType}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.message = "an entity name '%(name)s'"
|
self.message = "an entity name '%(name)s'"
|
||||||
return facet_evaluation(inst.is_a(self.name), self.message % {"name": inst.is_a()})
|
return facet_evaluation(
|
||||||
|
inst.is_a(self.name),
|
||||||
|
self.message % {"name": inst.is_a()}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class classification(facet):
|
class classification(facet):
|
||||||
@@ -124,8 +136,6 @@ class property(facet):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
parameters = ["name", "propertyset", "value"]
|
parameters = ["name", "propertyset", "value"]
|
||||||
|
|
||||||
# import pdb;pdb.set_trace()
|
|
||||||
message = "a property '%(name)s' in '%(propertyset)s' with value '%(value)s'"
|
message = "a property '%(name)s' in '%(propertyset)s' with value '%(value)s'"
|
||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
@@ -212,19 +222,24 @@ class restriction:
|
|||||||
self.options = []
|
self.options = []
|
||||||
self.type = []
|
self.type = []
|
||||||
|
|
||||||
for n in node.childNodes:
|
#TODO implement restrictions
|
||||||
if n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("enumeration"):
|
# for n in node.childNodes:
|
||||||
self.options.append(n.getAttribute("value"))
|
# if n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("enumeration"):
|
||||||
self.type = "enumeration"
|
# self.options.append(n.getAttribute("value"))
|
||||||
elif n.nodeType == n.ELEMENT_NODE and (n.tagName.endswith("Inclusive") or n.tagName.endswith("Exclusive")):
|
# self.type = "enumeration"
|
||||||
self.options.append(n.getAttribute("value"))
|
# elif n.nodeType == n.ELEMENT_NODE and (n.tagName.endswith("Inclusive") or n.tagName.endswith("Exclusive")):
|
||||||
self.type = "bounds"
|
# self.options.append(n.getAttribute("value"))
|
||||||
elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("length"):
|
# self.type = "bounds"
|
||||||
self.options.append(n.getAttribute("value"))
|
# elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("length"):
|
||||||
self.type = "length"
|
# self.options.append(n.getAttribute("value"))
|
||||||
elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("pattern"):
|
# self.type = "length"
|
||||||
self.options.append(n.getAttribute("value"))
|
# elif n.nodeType == n.ELEMENT_NODE and n.tagName.endswith("pattern"):
|
||||||
self.type = "pattern"
|
# self.options.append(n.getAttribute("value"))
|
||||||
|
# self.type = "pattern"
|
||||||
|
#TODO add min/maxLength
|
||||||
|
#TODO add fractionDigits
|
||||||
|
#TODO add totalDigits
|
||||||
|
#TODO add whiteSpace
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return other in self.options
|
return other in self.options
|
||||||
@@ -248,27 +263,22 @@ class specification:
|
|||||||
|
|
||||||
def __init__(self, node):
|
def __init__(self, node):
|
||||||
def parse_rules(node):
|
def parse_rules(node):
|
||||||
children = [n for n in node.childNodes if n.nodeType == n.ELEMENT_NODE]
|
children = [node[n][0] for n in node]
|
||||||
names = map(operator.attrgetter("tagName"), children)
|
names = [n for n in node]
|
||||||
classes = map(meta_facet.facets.__getitem__, names)
|
classes = map(meta_facet.facets.__getitem__, names)
|
||||||
return [cls(n) for cls, n in zip(classes, children)]
|
return [cls(n) for cls, n in zip(classes, children)]
|
||||||
|
|
||||||
phrases = [n for n in node.childNodes if n.nodeType == n.ELEMENT_NODE]
|
self.applicability = boolean_and(parse_rules(node['applicability']))
|
||||||
|
self.requirements = boolean_and(parse_rules(node['requirements']))
|
||||||
len(phrases) == 2 or error("expected two child nodes for <specification>")
|
|
||||||
phrases[0].tagName == "applicability" or error("expected <applicability>")
|
|
||||||
phrases[1].tagName == "requirements" or error("expected <requirements>")
|
|
||||||
|
|
||||||
self.applicability, self.requirements = (boolean_and(parse_rules(phrase)) for phrase in phrases)
|
|
||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
if self.applicability(inst, logger):
|
if self.applicability(inst, logger):
|
||||||
valid = self.requirements(inst, logger)
|
valid = self.requirements(inst, logger)
|
||||||
|
|
||||||
if valid:
|
if valid:
|
||||||
logger.info({'guid':inst.GlobalId, 'result':valid.success,'sentence':str(self) + "\n'" + inst.Name + "' (id:" + inst.GlobalId + ") has " + str(valid) + " so is compliant"})
|
logger.info({'guid':inst.GlobalId, 'result':valid.success,'sentence':str(self) + "\n" + inst.is_a() + " '" + str(inst.Name) + "' (#" + str(inst.id()) + ") has " + str(valid) + " so is compliant"})
|
||||||
else:
|
else:
|
||||||
logger.error({'guid':inst.GlobalId, 'result':valid.success, 'sentence':str(self) + "\n'" + inst.Name + "' (id:" + inst.GlobalId + ") has " + str(valid) + " so is not compliant"})
|
logger.error({'guid':inst.GlobalId, 'result':valid.success, 'sentence':str(self) + "\n" + inst.is_a() + " '" + str(inst.Name) + "' (#" + str(inst.id()) + ") has " + str(valid) + " so is not compliant"})
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "Given an instance with %(applicability)s\nWe expect %(requirements)s" % self.__dict__
|
return "Given an instance with %(applicability)s\nWe expect %(requirements)s" % self.__dict__
|
||||||
@@ -283,13 +293,8 @@ class ids:
|
|||||||
ids_schema = XMLSchema("http://standards.buildingsmart.org/IDS/ids.xsd")
|
ids_schema = XMLSchema("http://standards.buildingsmart.org/IDS/ids.xsd")
|
||||||
ids_schema.validate(fn)
|
ids_schema.validate(fn)
|
||||||
|
|
||||||
dom = parse(fn)
|
ids = ids_schema.to_dict(fn)
|
||||||
ids = dom.childNodes[0]
|
self.specifications = [specification(s) for s in ids['specification']]
|
||||||
ids.tagName == "ids" or error("expected <ids>")
|
|
||||||
|
|
||||||
self.specifications = [
|
|
||||||
specification(n) for n in ids.childNodes if n.nodeType == n.ELEMENT_NODE and n.tagName == "specification"
|
|
||||||
]
|
|
||||||
|
|
||||||
def validate(self, ifc_file, logger):
|
def validate(self, ifc_file, logger):
|
||||||
for spec in self.specifications:
|
for spec in self.specifications:
|
||||||
|
|||||||
Reference in New Issue
Block a user