sumolib.xml.xsd

  1# -*- coding: utf-8 -*-
  2# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
  3# Copyright (C) 2014-2026 German Aerospace Center (DLR) and others.
  4# This program and the accompanying materials are made available under the
  5# terms of the Eclipse Public License 2.0 which is available at
  6# https://www.eclipse.org/legal/epl-2.0/
  7# This Source Code may also be made available under the following Secondary
  8# Licenses when the conditions for such availability set forth in the Eclipse
  9# Public License 2.0 are satisfied: GNU General Public License, version 2
 10# or later which is available at
 11# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
 12# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 13
 14# @file    xsd.py
 15# @author  Marek Heinrich
 16# @author  Michael Behrisch
 17# @date    2014-01-20
 18
 19from __future__ import absolute_import
 20
 21import os
 22from xml.dom import minidom
 23
 24
 25class XmlAttribute:
 26
 27    def __init__(self, entity):
 28        if hasattr(entity, "getAttribute"):
 29            self.name = entity.getAttribute('name')
 30            self.use = entity.getAttribute('use')
 31            self.type = entity.getAttribute('type')
 32        else:
 33            self.name = entity
 34            self.use = None
 35            self.type = None
 36
 37    def __repr__(self):
 38        return self.name
 39
 40
 41class XmlElement:
 42
 43    def __init__(self, entity):
 44        self.name = entity.getAttribute('name')
 45        self.ref = entity.getAttribute('ref')
 46        self.type = entity.getAttribute('type')
 47        self.attributes = []
 48        self.children = []
 49        self.resolved = False
 50
 51    def __repr__(self):
 52        childList = [c.name for c in self.children]
 53        return "name '%s' ref '%s' type '%s' attrs %s %s" % (self.name, self.ref, self.type, self.attributes, childList)
 54
 55
 56class XsdStructure():
 57
 58    def __init__(self, xsdFile):
 59        with open(xsdFile) as xsdIn:
 60            xmlDoc = minidom.parse(xsdIn)
 61        self.root = None
 62        self._namedElements = {}
 63        self._namedTypes = {}
 64        self._namedEnumerations = {}
 65        for btEntity in xmlDoc.getElementsByTagName('xsd:include'):
 66            path = btEntity.getAttribute('schemaLocation')
 67            fullPath = os.path.join(os.path.dirname(xsdFile), path)
 68            subStruc = XsdStructure(fullPath)
 69            self._namedElements.update(subStruc._namedElements)
 70            self._namedTypes.update(subStruc._namedTypes)
 71        for btEntity in xmlDoc.getElementsByTagName('xsd:element'):
 72            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 73                el = self.getElementStructure(btEntity, True)
 74                self._namedElements[el.name] = el
 75                if self.root is None:
 76                    self.root = el
 77        for btEntity in xmlDoc.getElementsByTagName('xsd:complexType'):
 78            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 79                el = self.getElementStructure(btEntity)
 80                self._namedTypes[el.name] = el
 81        for btEntity in xmlDoc.getElementsByTagName('xsd:simpleType'):
 82            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 83                enum = [e.getAttribute(
 84                    'value') for e in btEntity.getElementsByTagName('xsd:enumeration')]
 85                if enum:
 86                    self._namedEnumerations[
 87                        btEntity.getAttribute('name')] = enum
 88        self.resolveRefs()
 89#        pp = pprint.PrettyPrinter(indent=4)
 90#        pp.pprint(self._namedElements)
 91#        pp.pprint(self._namedTypes)
 92#        pp.pprint(self._namedEnumerations)
 93
 94    def getEnumeration(self, name):
 95        return self._namedEnumerations.get(name, None)
 96
 97    def getEnumerationByAttr(self, ele, attr):
 98        if ele in self._namedElements:
 99            for a in self._namedElements[ele].attributes:
100                if a.name == attr:
101                    return self._namedEnumerations.get(a.type, None)
102        return None
103
104    def getElementStructure(self, entity, checkNestedType=False):
105        eleObj = XmlElement(entity)
106        if checkNestedType:
107            nestedTypes = entity.getElementsByTagName('xsd:complexType')
108            if nestedTypes:
109                entity = nestedTypes[0]  # skip xsd:complex-tag
110        for ext in entity.getElementsByTagName('xsd:extension'):
111            if ext.parentNode.parentNode == entity:
112                eleObj.type = ext.getAttribute('base')
113                entity = ext
114                break
115        for aa in entity.childNodes:
116            if aa.nodeName == 'xsd:attribute':
117                eleObj.attributes.append(XmlAttribute(aa))
118            elif aa.nodeName == 'xsd:sequence' or aa.nodeName == 'xsd:choice':
119                for aae in aa.getElementsByTagName('xsd:element'):
120                    eleObj.children.append(XmlElement(aae))
121        return eleObj
122
123    def resolveRefs(self):
124        for ele in self._namedTypes.values():
125            if ele.type and ele.type in self._namedTypes and not ele.resolved:
126                t = self._namedTypes[ele.type]
127                ele.attributes += t.attributes
128                ele.children += t.children
129                ele.resolved = True
130        for ele in self._namedElements.values():
131            if ele.type and ele.type in self._namedTypes and not ele.resolved:
132                t = self._namedTypes[ele.type]
133                ele.attributes += t.attributes
134                ele.children += t.children
135                ele.resolved = True
136        for ele in self._namedElements.values():
137            newChildren = []
138            for child in ele.children:
139                if child.ref:
140                    newChildren.append(self._namedElements[child.ref])
141                else:
142                    newChildren.append(self._namedElements[child.name])
143            ele.children = newChildren
class XmlAttribute:
26class XmlAttribute:
27
28    def __init__(self, entity):
29        if hasattr(entity, "getAttribute"):
30            self.name = entity.getAttribute('name')
31            self.use = entity.getAttribute('use')
32            self.type = entity.getAttribute('type')
33        else:
34            self.name = entity
35            self.use = None
36            self.type = None
37
38    def __repr__(self):
39        return self.name
XmlAttribute(entity)
28    def __init__(self, entity):
29        if hasattr(entity, "getAttribute"):
30            self.name = entity.getAttribute('name')
31            self.use = entity.getAttribute('use')
32            self.type = entity.getAttribute('type')
33        else:
34            self.name = entity
35            self.use = None
36            self.type = None
class XmlElement:
42class XmlElement:
43
44    def __init__(self, entity):
45        self.name = entity.getAttribute('name')
46        self.ref = entity.getAttribute('ref')
47        self.type = entity.getAttribute('type')
48        self.attributes = []
49        self.children = []
50        self.resolved = False
51
52    def __repr__(self):
53        childList = [c.name for c in self.children]
54        return "name '%s' ref '%s' type '%s' attrs %s %s" % (self.name, self.ref, self.type, self.attributes, childList)
XmlElement(entity)
44    def __init__(self, entity):
45        self.name = entity.getAttribute('name')
46        self.ref = entity.getAttribute('ref')
47        self.type = entity.getAttribute('type')
48        self.attributes = []
49        self.children = []
50        self.resolved = False
name
ref
type
attributes
children
resolved
class XsdStructure:
 57class XsdStructure():
 58
 59    def __init__(self, xsdFile):
 60        with open(xsdFile) as xsdIn:
 61            xmlDoc = minidom.parse(xsdIn)
 62        self.root = None
 63        self._namedElements = {}
 64        self._namedTypes = {}
 65        self._namedEnumerations = {}
 66        for btEntity in xmlDoc.getElementsByTagName('xsd:include'):
 67            path = btEntity.getAttribute('schemaLocation')
 68            fullPath = os.path.join(os.path.dirname(xsdFile), path)
 69            subStruc = XsdStructure(fullPath)
 70            self._namedElements.update(subStruc._namedElements)
 71            self._namedTypes.update(subStruc._namedTypes)
 72        for btEntity in xmlDoc.getElementsByTagName('xsd:element'):
 73            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 74                el = self.getElementStructure(btEntity, True)
 75                self._namedElements[el.name] = el
 76                if self.root is None:
 77                    self.root = el
 78        for btEntity in xmlDoc.getElementsByTagName('xsd:complexType'):
 79            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 80                el = self.getElementStructure(btEntity)
 81                self._namedTypes[el.name] = el
 82        for btEntity in xmlDoc.getElementsByTagName('xsd:simpleType'):
 83            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
 84                enum = [e.getAttribute(
 85                    'value') for e in btEntity.getElementsByTagName('xsd:enumeration')]
 86                if enum:
 87                    self._namedEnumerations[
 88                        btEntity.getAttribute('name')] = enum
 89        self.resolveRefs()
 90#        pp = pprint.PrettyPrinter(indent=4)
 91#        pp.pprint(self._namedElements)
 92#        pp.pprint(self._namedTypes)
 93#        pp.pprint(self._namedEnumerations)
 94
 95    def getEnumeration(self, name):
 96        return self._namedEnumerations.get(name, None)
 97
 98    def getEnumerationByAttr(self, ele, attr):
 99        if ele in self._namedElements:
100            for a in self._namedElements[ele].attributes:
101                if a.name == attr:
102                    return self._namedEnumerations.get(a.type, None)
103        return None
104
105    def getElementStructure(self, entity, checkNestedType=False):
106        eleObj = XmlElement(entity)
107        if checkNestedType:
108            nestedTypes = entity.getElementsByTagName('xsd:complexType')
109            if nestedTypes:
110                entity = nestedTypes[0]  # skip xsd:complex-tag
111        for ext in entity.getElementsByTagName('xsd:extension'):
112            if ext.parentNode.parentNode == entity:
113                eleObj.type = ext.getAttribute('base')
114                entity = ext
115                break
116        for aa in entity.childNodes:
117            if aa.nodeName == 'xsd:attribute':
118                eleObj.attributes.append(XmlAttribute(aa))
119            elif aa.nodeName == 'xsd:sequence' or aa.nodeName == 'xsd:choice':
120                for aae in aa.getElementsByTagName('xsd:element'):
121                    eleObj.children.append(XmlElement(aae))
122        return eleObj
123
124    def resolveRefs(self):
125        for ele in self._namedTypes.values():
126            if ele.type and ele.type in self._namedTypes and not ele.resolved:
127                t = self._namedTypes[ele.type]
128                ele.attributes += t.attributes
129                ele.children += t.children
130                ele.resolved = True
131        for ele in self._namedElements.values():
132            if ele.type and ele.type in self._namedTypes and not ele.resolved:
133                t = self._namedTypes[ele.type]
134                ele.attributes += t.attributes
135                ele.children += t.children
136                ele.resolved = True
137        for ele in self._namedElements.values():
138            newChildren = []
139            for child in ele.children:
140                if child.ref:
141                    newChildren.append(self._namedElements[child.ref])
142                else:
143                    newChildren.append(self._namedElements[child.name])
144            ele.children = newChildren
XsdStructure(xsdFile)
59    def __init__(self, xsdFile):
60        with open(xsdFile) as xsdIn:
61            xmlDoc = minidom.parse(xsdIn)
62        self.root = None
63        self._namedElements = {}
64        self._namedTypes = {}
65        self._namedEnumerations = {}
66        for btEntity in xmlDoc.getElementsByTagName('xsd:include'):
67            path = btEntity.getAttribute('schemaLocation')
68            fullPath = os.path.join(os.path.dirname(xsdFile), path)
69            subStruc = XsdStructure(fullPath)
70            self._namedElements.update(subStruc._namedElements)
71            self._namedTypes.update(subStruc._namedTypes)
72        for btEntity in xmlDoc.getElementsByTagName('xsd:element'):
73            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
74                el = self.getElementStructure(btEntity, True)
75                self._namedElements[el.name] = el
76                if self.root is None:
77                    self.root = el
78        for btEntity in xmlDoc.getElementsByTagName('xsd:complexType'):
79            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
80                el = self.getElementStructure(btEntity)
81                self._namedTypes[el.name] = el
82        for btEntity in xmlDoc.getElementsByTagName('xsd:simpleType'):
83            if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
84                enum = [e.getAttribute(
85                    'value') for e in btEntity.getElementsByTagName('xsd:enumeration')]
86                if enum:
87                    self._namedEnumerations[
88                        btEntity.getAttribute('name')] = enum
89        self.resolveRefs()
root
def getEnumeration(self, name):
95    def getEnumeration(self, name):
96        return self._namedEnumerations.get(name, None)
def getEnumerationByAttr(self, ele, attr):
 98    def getEnumerationByAttr(self, ele, attr):
 99        if ele in self._namedElements:
100            for a in self._namedElements[ele].attributes:
101                if a.name == attr:
102                    return self._namedEnumerations.get(a.type, None)
103        return None
def getElementStructure(self, entity, checkNestedType=False):
105    def getElementStructure(self, entity, checkNestedType=False):
106        eleObj = XmlElement(entity)
107        if checkNestedType:
108            nestedTypes = entity.getElementsByTagName('xsd:complexType')
109            if nestedTypes:
110                entity = nestedTypes[0]  # skip xsd:complex-tag
111        for ext in entity.getElementsByTagName('xsd:extension'):
112            if ext.parentNode.parentNode == entity:
113                eleObj.type = ext.getAttribute('base')
114                entity = ext
115                break
116        for aa in entity.childNodes:
117            if aa.nodeName == 'xsd:attribute':
118                eleObj.attributes.append(XmlAttribute(aa))
119            elif aa.nodeName == 'xsd:sequence' or aa.nodeName == 'xsd:choice':
120                for aae in aa.getElementsByTagName('xsd:element'):
121                    eleObj.children.append(XmlElement(aae))
122        return eleObj
def resolveRefs(self):
124    def resolveRefs(self):
125        for ele in self._namedTypes.values():
126            if ele.type and ele.type in self._namedTypes and not ele.resolved:
127                t = self._namedTypes[ele.type]
128                ele.attributes += t.attributes
129                ele.children += t.children
130                ele.resolved = True
131        for ele in self._namedElements.values():
132            if ele.type and ele.type in self._namedTypes and not ele.resolved:
133                t = self._namedTypes[ele.type]
134                ele.attributes += t.attributes
135                ele.children += t.children
136                ele.resolved = True
137        for ele in self._namedElements.values():
138            newChildren = []
139            for child in ele.children:
140                if child.ref:
141                    newChildren.append(self._namedElements[child.ref])
142                else:
143                    newChildren.append(self._namedElements[child.name])
144            ele.children = newChildren