我有一个Solace JMS Messaging Box,我正在自动管理,并且该设备使用大量非常小的XML帖子进行配置。由于设备在其XML规范中有如此多的命令,我需要一种方法来创建任意XML请求。
XML看起来像:
<rpc semp-version="soltr/5_5">
<create>
<message-vpn>
<vpn-name>developer.testvpn</vpn-name>
</message-vpn>
</create>
</rpc>
第二次更改设置的调用可能如下所示:
<rpc semp-version="soltr/5_5">
<message-vpn>
<vpn-name>developer.testvpn</vpn-name>
<export-policy>
<no>
<export-subscriptions/>
</no>
</export-policy>
</message-vpn>
</rpc>
由于XML规范中有许多命令,我正在寻找一种从点名称空间中自由创建它们的方法。例如:
mycall = SolaceXML()
mycall.create.message_vpn.vpn_name="developer.testvpn"
mycall.message_vpn.vpn_name='developer.testvpn'
mycall.message_vpn.export_policy.no.export_subscription
更新 我在下面发布了我的解决方案。它不像我想的那么小但它对我有用。
ķ
答案 0 :(得分:0)
我找到了一个解决方案。希望这有助于其他人。此解决方案从点名称空间调用构建嵌套字典对象,然后将其转换为XML。
from xml.dom.minidom import Document
import copy
import re
from collections import OrderedDict
class d2x:
''' Converts Dictionary to XML '''
def __init__(self, structure):
self.doc = Document()
if len(structure) == 1:
rootName = str(structure.keys()[0])
self.root = self.doc.createElement(rootName)
self.doc.appendChild(self.root)
self.build(self.root, structure[rootName])
def build(self, father, structure):
if type(structure) == dict:
for k in structure:
tag = self.doc.createElement(k)
father.appendChild(tag)
self.build(tag, structure[k])
elif type(structure) == OrderedDict:
for k in structure:
tag = self.doc.createElement(k)
father.appendChild(tag)
self.build(tag, structure[k])
elif type(structure) == list:
grandFather = father.parentNode
tagName = father.tagName
grandFather.removeChild(father)
for l in structure:
tag = self.doc.createElement(tagName)
self.build(tag, l)
grandFather.appendChild(tag)
else:
data = str(structure)
tag = self.doc.createTextNode(data)
father.appendChild(tag)
def display(self):
# I render from the root instead of doc to get rid of the XML header
#return self.root.toprettyxml(indent=" ")
return self.root.toxml()
class SolaceNode:
''' a sub dictionary builder '''
def __init__(self):
self.__dict__ = OrderedDict()
def __getattr__(self, name):
name = re.sub("_", "-", name)
try:
return self.__dict__[name]
except:
self.__dict__[name] = SolaceNode()
return self.__dict__[name]
def __str__(self):
return str(self.__dict__)
def __repr__(self):
return str(self.__dict__)
def __call__(self, *args, **kwargs):
return self.__dict__
def __setattr__(self, name, value):
name = re.sub("_", "-", name)
self.__dict__[name] = value
class SolaceXMLBuilder(object):
''' main dictionary builder
Any dot-name-space like calling of a instance of SolaceXMLBuilder will create
nested dictionary keys. These are converted to XML whenever the instance
representation is called ( __repr__ )
Example
a=SolaceXMLBuilder()
a.foo.bar.baz=2
str(a)
'<rpc semp-version="soltr/5_5">\n<foo><bar><baz>2</baz></bar></foo></rpc>'
'''
def __init__(self):
self.__dict__ = OrderedDict()
self.__setattr__ = None
def __getattr__(self, name):
name = re.sub("_", "-", name)
try:
return self.__dict__[name]
except:
self.__dict__[name] = SolaceNode()
return self.__dict__[name]
def __repr__(self):
# Show XML
myxml = d2x(eval(str(self.__dict__)))
# I had to conjur up my own header cause solace doesnt like </rpc> to have attribs
#return str('<rpc semp-version="soltr/5_5">\n%s</rpc>' % myxml.display())
return str('<rpc semp-version="soltr/5_5">\n%s</rpc>' % myxml.display())
def __call__(self, *args, **kwargs):
return self.__dict__
# def __setattr__(self, name, value):
# raise Exception('no you cant create assignments here, only on sub-elements')
if __name__ == '__main__':
x = SolaceXMLBuilder()
x.create.message_vpn.vpn_name='NEWVPN'
print(x)
# <?xml version="1.0" ?>
# <rpc semp-version="soltr/5_5">
# <create>
# <message-vpn>
# <vpn-name>
# NEWVPN
# </vpn-name>
# </message-vpn>
# </create>
# </rpc semp-version="soltr/5_5">
x=SolaceXMLBuilder()
x.message_vpn.vpn_name='NEWVPN'
x.message_vpn.no.feature_X
print(x)
# <?xml version="1.0" ?>
# <rpc semp-version="soltr/5_5">
# <message-vpn>
# <vpn-name>
# NEWVPN
# </vpn-name>
# <no>
# <feature-X/>
# </no>
# </message-vpn>
# </rpc semp-version="soltr/5_5">
# >>> client = SolaceAPI('pt1')
# >>> xml = SolaceXMLBuilder()
# >>> xml.create.message_vpn.vpn_name='NEWVPN'
# >>> client.rpc(str(xml))
# {u'rpc-reply': {u'execute-result': {u'@code': u'ok'}, u'@semp-version': u'soltr/5_5'}}