-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathxsd.py
More file actions
144 lines (125 loc) · 5.44 KB
/
xsd.py
File metadata and controls
144 lines (125 loc) · 5.44 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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# -*- coding: utf-8 -*-
"""
@file xsd.py
@author Marek Heinrich
@author Michael Behrisch
@date 2014-01-20
@version $Id: xsd.py 20433 2016-04-13 08:00:14Z behrisch $
Helper classes for parsing xsd schemata.
SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
Copyright (C) 2014-2016 DLR (http://www.dlr.de/) and contributors
This file is part of SUMO.
SUMO is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
"""
from __future__ import absolute_import
import os
import pprint
from xml.dom import minidom
class XmlAttribute:
def __init__(self, entity):
if hasattr(entity, "getAttribute"):
self.name = entity.getAttribute('name')
self.use = entity.getAttribute('use')
self.type = entity.getAttribute('type')
else:
self.name = entity
self.use = None
self.type = None
def __repr__(self):
return self.name
class XmlElement:
def __init__(self, entity):
self.name = entity.getAttribute('name')
self.ref = entity.getAttribute('ref')
self.type = entity.getAttribute('type')
self.attributes = []
self.children = []
self.resolved = False
def __repr__(self):
childList = [c.name for c in self.children]
return "name '%s' ref '%s' type '%s' attrs %s %s" % (self.name, self.ref, self.type, self.attributes, childList)
class XsdStructure():
def __init__(self, xsdFile):
xmlDoc = minidom.parse(open(xsdFile))
self.root = None
self._namedElements = {}
self._namedTypes = {}
self._namedEnumerations = {}
for btEntity in xmlDoc.getElementsByTagName('xsd:include'):
path = btEntity.getAttribute('schemaLocation')
fullPath = os.path.join(os.path.dirname(xsdFile), path)
subStruc = XsdStructure(fullPath)
self._namedElements.update(subStruc._namedElements)
self._namedTypes.update(subStruc._namedTypes)
for btEntity in xmlDoc.getElementsByTagName('xsd:element'):
if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
el = self.getElementStructure(btEntity, True)
self._namedElements[el.name] = el
if self.root is None:
self.root = el
for btEntity in xmlDoc.getElementsByTagName('xsd:complexType'):
if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
el = self.getElementStructure(btEntity)
self._namedTypes[el.name] = el
for btEntity in xmlDoc.getElementsByTagName('xsd:simpleType'):
if btEntity.nodeType == 1 and btEntity.hasAttribute('name'):
enum = [e.getAttribute(
'value') for e in btEntity.getElementsByTagName('xsd:enumeration')]
if enum:
self._namedEnumerations[
btEntity.getAttribute('name')] = enum
self.resolveRefs()
# pp = pprint.PrettyPrinter(indent=4)
# pp.pprint(self._namedElements)
# pp.pprint(self._namedTypes)
# pp.pprint(self._namedEnumerations)
def getEnumeration(self, name):
return self._namedEnumerations.get(name, None)
def getEnumerationByAttr(self, ele, attr):
if ele in self._namedElements:
for a in self._namedElements[ele].attributes:
if a.name == attr:
return self._namedEnumerations.get(a.type, None)
return None
def getElementStructure(self, entity, checkNestedType=False):
eleObj = XmlElement(entity)
if checkNestedType:
nestedTypes = entity.getElementsByTagName('xsd:complexType')
if nestedTypes:
entity = nestedTypes[0] # skip xsd:complex-tag
for ext in entity.getElementsByTagName('xsd:extension'):
if ext.parentNode.parentNode == entity:
eleObj.type = ext.getAttribute('base')
entity = ext
break
for aa in entity.childNodes:
if aa.nodeName == 'xsd:attribute':
eleObj.attributes.append(XmlAttribute(aa))
elif aa.nodeName == 'xsd:sequence' or aa.nodeName == 'xsd:choice':
for aae in aa.getElementsByTagName('xsd:element'):
eleObj.children.append(XmlElement(aae))
return eleObj
def resolveRefs(self):
for ele in self._namedTypes.values():
if ele.type and ele.type in self._namedTypes and not ele.resolved:
t = self._namedTypes[ele.type]
ele.attributes += t.attributes
ele.children += t.children
ele.resolved = True
for ele in self._namedElements.values():
if ele.type and ele.type in self._namedTypes and not ele.resolved:
t = self._namedTypes[ele.type]
ele.attributes += t.attributes
ele.children += t.children
ele.resolved = True
for ele in self._namedElements.values():
newChildren = []
for child in ele.children:
if child.ref:
newChildren.append(self._namedElements[child.ref])
else:
newChildren.append(self._namedElements[child.name])
ele.children = newChildren