1

私は管理を自動化している 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>

設定を変更するための 2 回目の呼び出しは、次のようになります。

<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

更新 私は私の解決策を以下に掲載しました。私が望むほど小さくはありませんが、私にとってはうまくいきます。

K

4

1 に答える 1

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'}}
于 2012-11-30T14:42:30.327 に答える