Итак, я извлекаю данные из одного vShield Manager через API и создаю базу данных для синхронизации с другим ... Я успешно возвращаю XML из API (yay), и я могу разобрать его просто отлично, но это немного утомительно. Я пытаюсь создать пользовательские классы для различных объектов в vShield (виртуальные брандмауэры, глобальные объекты адресов, определения сервисов и т. Д.), Поэтому я могу правильно ссылаться на данные в моем сценарии, и именно здесь я нарваться проблемы (вроде) ...XML для пользовательского класса
Я получаю XML обратно который выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8"?>
<scopingObjects>
<object>
<objectId>datacenter-2</objectId>
<type>
<typeName>Datacenter</typeName>
</type>
<name>virtualDataCenter-01</name>
<revision>5</revision>
<objectTypeName>Datacenter</objectTypeName>
<scope>
<id>group-d1</id>
<objectTypeName>Folder</objectTypeName>
<name>Datacenters</name>
</scope>
<extendedAttributes/>
</object>
<object>
<objectId>globalroot-0</objectId>
<type>
<typeName>GlobalRoot</typeName>
</type>
<name>Global</name>
<revision>460</revision>
<objectTypeName>GlobalRoot</objectTypeName>
<extendedAttributes/>
</object>
</scopingObjects>
И я itterate через это с помощью ElementTree:
# Get the list of scoping objects
scopeObjects = [] # Declare an empty list
r = sendRest("getScopes")
xml = et.fromstring(r.text)
for object in xml.iter("object"):
try:
o = scope()
o.create(et.tostring(object))
scopeObjects.append(o)
except Exception, e:
print "Exception: " + repr(e)
Где я использую определение следующего класса:
class scope:
def __init__(self):
self.id = ""
self.name = ""
self.type = ""
def create(self, xmlString):
try:
xml = et.fromstring(xmlString)
if xml.find("objectId") is not None: self.id = xml.find("objectId").text
if xml.find("name") is not None: self.name = xml.find("name").text
if xml.find("type/typeName") is not None: self.type = xml.find("type/typeName").text
except:
print "Error constructing scope object from:\n%s" % xmlString
return False
Что все работает, до тех пор, пока я не сталкиваюсь с более сложными структурами XML ... тогда это оргия «если xml.find (« blah/blah/blah ») не является None: variable . = xml.find («бла/бла/бла») текст»снова и снова ...
Я хотел бы сделать что-то вроде:
class scope:
def __init__(self):
self.id = ""
self.name = ""
self.type = ""
def create(self, xmlString):
xmlPaths = { "id" : "objectId", "name" : "name", "type" : "type/typeName" }
for key in xmlPaths.keys():
element = xml.find(xmlPaths[key])
if element is not None:
# Set the class property named by "key" to the value of element.text
locals()[key] = element.text
# For example, if the key is "id", then it sets "self.id" to the text of the element in XML tag "<objectId>"
в принципе, я хочу быть ленивым когда дело доходит до построения объектов ... Я не хочу набирать нагрузки «if xml ....». Это станет намного более важным, когда я начну работать с более сложными объектами, возвращаемыми API, с множеством элементов, с которыми нужно иметь дело.
Мой основной вопрос: что это лучший способ сделать это?
Cheers!
Мое решение:
Огромное спасибо Larsks за ответ. Привет, друг!
class scope:
xmlPathMap = {
"id" : "objectId",
"name" : "name",
"type" : "type/typeName"
}
def __init__(self, element):
self.element = element
self.create()
def create(self):
try:
for key, path in self.xmlPathMap.items():
res = self.element.find(path)
if res is not None:
setattr(self, key, res.text)
except:
print "Error constructing scope object:\n\tkey: %s\n\tpath: %s\n\tvalue: %s" % (key, path, res.text)
return False
# End of scope class definition
Почему вы называете 'o.create (et.tostring (объект))', а затем в 'create' немедленного вызова' XML = et.fromstring (xmlString) '? Почему бы просто не передать «объект» без сериализации/десериализации? – larsks