add GCAP interface
Showing
3 changed files
with
402 additions
and
0 deletions
| ... | @@ -1004,3 +1004,17 @@ ID_TYPE = ['ITARI', 'ITHKM', 'ITPRC', 'ITPSP', 'ITRES', 'ITTID', 'ITUSC', 'ITCCU | ... | @@ -1004,3 +1004,17 @@ ID_TYPE = ['ITARI', 'ITHKM', 'ITPRC', 'ITPSP', 'ITRES', 'ITTID', 'ITUSC', 'ITCCU |
| 1004 | SECOND_ID_TYPE = ['ITARI', 'ITHKM', 'ITPRC', 'ITPSP', 'ITRES', 'ITTID'] | 1004 | SECOND_ID_TYPE = ['ITARI', 'ITHKM', 'ITPRC', 'ITPSP', 'ITRES', 'ITTID'] |
| 1005 | SUB_TYPE = ['CSIBM', 'CSOTH', 'CSSME'] | 1005 | SUB_TYPE = ['CSIBM', 'CSOTH', 'CSSME'] |
| 1006 | 1006 | ||
| 1007 | # GCAP 请求体 | ||
| 1008 | BASE_XML_TEXT = """<?xml version="1.0" encoding="utf-8"?> | ||
| 1009 | |||
| 1010 | <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:typ="http://guardean.net/webservices/workflow/vatra_bmwservice/types"> | ||
| 1011 | <soapenv:Header/> | ||
| 1012 | <soapenv:Body> | ||
| 1013 | <typ:executeRequest> | ||
| 1014 | <request>{0}</request> | ||
| 1015 | </typ:executeRequest> | ||
| 1016 | </soapenv:Body> | ||
| 1017 | </soapenv:Envelope>""" | ||
| 1018 | |||
| 1019 | CDATA_TEXT = """<![CDATA[<Exec xmlns="http://tempuri.org/"><strXMLParm><Request><Framework><UserName>SFCHINA\qqcout0</UserName><GUID>70d0efcb-3bc2-4018-ac4e-681c8f3131b6</GUID><DetailedTracingEnabled>False</DetailedTracingEnabled><ServiceName>AMSWebService</ServiceName><SupportsRedirection>true</SupportsRedirection><ServiceType>Service</ServiceType></Framework><Parms><InputXML type="string">&lt;?xml version="1.0" encoding="utf-16"?&gt;&lt;InputXML&gt; &lt;Result&gt; {0} &lt;/Result&gt;&lt;AuthorizationData&gt;&lt;ServiceComponent&gt;OCR&lt;/ServiceComponent&gt;&lt;RoleId/&gt;&lt;CompanyId/&gt;&lt;/AuthorizationData&gt;&lt;/InputXML&gt;</InputXML></Parms></Request></strXMLParm></Exec>]]>""" | ||
| 1020 | ... | ... |
src/apps/doc/ocr/gcap.py
0 → 100644
| 1 | import requests | ||
| 2 | from requests.auth import HTTPBasicAuth | ||
| 3 | from settings import conf | ||
| 4 | from common.tools.dict_to_xml import dicttoxml, escape_xml | ||
| 5 | from apps.doc import consts | ||
| 6 | |||
| 7 | |||
| 8 | class GCAP: | ||
| 9 | |||
| 10 | def __init__(self): | ||
| 11 | self.url = conf.GCAP_URL | ||
| 12 | self.headers = { | ||
| 13 | 'Content-Type': 'text/plain', | ||
| 14 | } | ||
| 15 | self.auth = HTTPBasicAuth(conf.GCAP_AUTH_USER, conf.GCAP_AUTH_PWD) | ||
| 16 | |||
| 17 | @staticmethod | ||
| 18 | def dict_to_xml(comparison_res): | ||
| 19 | comparison_xml = dicttoxml(comparison_res, root=False, attr_type=False) | ||
| 20 | return consts.BASE_XML_TEXT.format(consts.CDATA_TEXT.format(escape_xml(comparison_xml))).encode('utf-8') | ||
| 21 | |||
| 22 | def send(self, comparison_res): | ||
| 23 | data = self.dict_to_xml(comparison_res) | ||
| 24 | response = requests.post(self.url, headers=self.headers, data=data, verify=False, auth=self.auth) | ||
| 25 | return response | ||
| 26 | |||
| 27 | |||
| 28 | |||
| 29 |
src/common/tools/dict_to_xml.py
0 → 100644
| 1 | #!/usr/bin/env python | ||
| 2 | # coding: utf-8 | ||
| 3 | |||
| 4 | """ | ||
| 5 | Converts a Python dictionary or other native data type into a valid XML string. | ||
| 6 | Supports item (`int`, `float`, `long`, `decimal.Decimal`, `bool`, `str`, `unicode`, `datetime`, `none` and other number-like objects) and collection (`list`, `set`, `tuple` and `dict`, as well as iterable and dict-like objects) data types, with arbitrary nesting for the collections. Items with a `datetime` type are converted to ISO format strings. Items with a `None` type become empty XML elements. | ||
| 7 | This module works with both Python 2 and 3. | ||
| 8 | """ | ||
| 9 | |||
| 10 | from __future__ import unicode_literals | ||
| 11 | |||
| 12 | from random import randint | ||
| 13 | import collections | ||
| 14 | import numbers | ||
| 15 | from xml.dom.minidom import parseString | ||
| 16 | |||
| 17 | # python 3 doesn't have a unicode type | ||
| 18 | unicode = str | ||
| 19 | |||
| 20 | # python 3 doesn't have a long type | ||
| 21 | long = int | ||
| 22 | |||
| 23 | |||
| 24 | def set_debug(debug=True, filename='dicttoxml.log'): | ||
| 25 | if debug: | ||
| 26 | import datetime | ||
| 27 | print('Debug mode is on. Events are logged at: %s' % (filename)) | ||
| 28 | else: | ||
| 29 | print('Debug mode is off.') | ||
| 30 | |||
| 31 | |||
| 32 | def unicode_me(something): | ||
| 33 | """Converts strings with non-ASCII characters to unicode for LOG. | ||
| 34 | Python 3 doesn't have a `unicode()` function, so `unicode()` is an alias | ||
| 35 | for `str()`, but `str()` doesn't take a second argument, hence this kludge. | ||
| 36 | """ | ||
| 37 | try: | ||
| 38 | return unicode(something, 'utf-8') | ||
| 39 | except: | ||
| 40 | return unicode(something) | ||
| 41 | |||
| 42 | |||
| 43 | ids = [] # initialize list of unique ids | ||
| 44 | |||
| 45 | |||
| 46 | def make_id(element, start=100000, end=999999): | ||
| 47 | """Returns a random integer""" | ||
| 48 | return '%s_%s' % (element, randint(start, end)) | ||
| 49 | |||
| 50 | |||
| 51 | def get_unique_id(element): | ||
| 52 | """Returns a unique id for a given element""" | ||
| 53 | this_id = make_id(element) | ||
| 54 | dup = True | ||
| 55 | while dup: | ||
| 56 | if this_id not in ids: | ||
| 57 | dup = False | ||
| 58 | ids.append(this_id) | ||
| 59 | else: | ||
| 60 | this_id = make_id(element) | ||
| 61 | return ids[-1] | ||
| 62 | |||
| 63 | |||
| 64 | def get_xml_type(val): | ||
| 65 | """Returns the data type for the xml type attribute""" | ||
| 66 | if type(val).__name__ in ('str', 'unicode'): | ||
| 67 | return 'str' | ||
| 68 | if type(val).__name__ in ('int', 'long'): | ||
| 69 | return 'int' | ||
| 70 | if type(val).__name__ == 'float': | ||
| 71 | return 'float' | ||
| 72 | if type(val).__name__ == 'bool': | ||
| 73 | return 'bool' | ||
| 74 | if isinstance(val, numbers.Number): | ||
| 75 | return 'number' | ||
| 76 | if type(val).__name__ == 'NoneType': | ||
| 77 | return 'null' | ||
| 78 | if isinstance(val, dict): | ||
| 79 | return 'dict' | ||
| 80 | if isinstance(val, collections.Iterable): | ||
| 81 | return 'list' | ||
| 82 | return type(val).__name__ | ||
| 83 | |||
| 84 | |||
| 85 | def escape_xml(s): | ||
| 86 | if type(s) in (str, unicode): | ||
| 87 | s = unicode_me(s) # avoid UnicodeDecodeError | ||
| 88 | s = s.replace('&', '&') | ||
| 89 | s = s.replace('"', '&quot;') | ||
| 90 | s = s.replace('\'', '&apos;') | ||
| 91 | s = s.replace('<', '&lt;') | ||
| 92 | s = s.replace('>', '&gt;') | ||
| 93 | return s | ||
| 94 | |||
| 95 | |||
| 96 | def make_attrstring(attr): | ||
| 97 | """Returns an attribute string in the form key="val" """ | ||
| 98 | attrstring = ' '.join(['%s="%s"' % (k, v) for k, v in attr.items()]) | ||
| 99 | return '%s%s' % (' ' if attrstring != '' else '', attrstring) | ||
| 100 | |||
| 101 | |||
| 102 | def key_is_valid_xml(key): | ||
| 103 | """Checks that a key is a valid XML name""" | ||
| 104 | test_xml = '<?xml version="1.0" encoding="UTF-8" ?><%s>foo</%s>' % (key, key) | ||
| 105 | try: | ||
| 106 | parseString(test_xml) | ||
| 107 | return True | ||
| 108 | except Exception: # minidom does not implement exceptions well | ||
| 109 | return False | ||
| 110 | |||
| 111 | |||
| 112 | def make_valid_xml_name(key, attr): | ||
| 113 | """Tests an XML name and fixes it if invalid""" | ||
| 114 | key = escape_xml(key) | ||
| 115 | attr = escape_xml(attr) | ||
| 116 | |||
| 117 | # pass through if key is already valid | ||
| 118 | if key_is_valid_xml(key): | ||
| 119 | return key, attr | ||
| 120 | |||
| 121 | # prepend a lowercase n if the key is numeric | ||
| 122 | if key.isdigit(): | ||
| 123 | return 'n%s' % (key), attr | ||
| 124 | |||
| 125 | # replace spaces with underscores if that fixes the problem | ||
| 126 | if key_is_valid_xml(key.replace(' ', '_')): | ||
| 127 | return key.replace(' ', '_'), attr | ||
| 128 | |||
| 129 | # key is still invalid - move it into a name attribute | ||
| 130 | attr['name'] = key | ||
| 131 | key = 'key' | ||
| 132 | return key, attr | ||
| 133 | |||
| 134 | |||
| 135 | def wrap_cdata(s): | ||
| 136 | """Wraps a string into CDATA sections""" | ||
| 137 | s = unicode_me(s).replace(']]>', ']]]]><![CDATA[>') | ||
| 138 | return '<![CDATA[' + s + ']]>' | ||
| 139 | |||
| 140 | |||
| 141 | def default_item_func(parent): | ||
| 142 | return 'item' | ||
| 143 | |||
| 144 | |||
| 145 | def convert(obj, ids, attr_type, item_func, cdata, parent='root'): | ||
| 146 | """Routes the elements of an object to the right function to convert them | ||
| 147 | based on their data type""" | ||
| 148 | |||
| 149 | item_name = item_func(parent) | ||
| 150 | |||
| 151 | if isinstance(obj, numbers.Number) or type(obj) in (str, unicode): | ||
| 152 | return convert_kv(item_name, obj, attr_type, cdata) | ||
| 153 | |||
| 154 | if hasattr(obj, 'isoformat'): | ||
| 155 | return convert_kv(item_name, obj.isoformat(), attr_type, cdata) | ||
| 156 | |||
| 157 | if type(obj) == bool: | ||
| 158 | return convert_bool(item_name, obj, attr_type, cdata) | ||
| 159 | |||
| 160 | if obj is None: | ||
| 161 | return convert_none(item_name, '', attr_type, cdata) | ||
| 162 | |||
| 163 | if isinstance(obj, dict): | ||
| 164 | return convert_dict(obj, ids, parent, attr_type, item_func, cdata) | ||
| 165 | |||
| 166 | if isinstance(obj, collections.Iterable): | ||
| 167 | return convert_list(obj, ids, parent, attr_type, item_func, cdata) | ||
| 168 | |||
| 169 | raise TypeError('Unsupported data type: %s (%s)' % (obj, type(obj).__name__)) | ||
| 170 | |||
| 171 | |||
| 172 | def convert_dict(obj, ids, parent, attr_type, item_func, cdata): | ||
| 173 | """Converts a dict into an XML string.""" | ||
| 174 | output = [] | ||
| 175 | addline = output.append | ||
| 176 | |||
| 177 | item_name = item_func(parent) | ||
| 178 | |||
| 179 | for key, val in obj.items(): | ||
| 180 | |||
| 181 | attr = {} if not ids else {'id': '%s' % (get_unique_id(parent))} | ||
| 182 | |||
| 183 | key, attr = make_valid_xml_name(key, attr) | ||
| 184 | |||
| 185 | if isinstance(val, numbers.Number) or type(val) in (str, unicode): | ||
| 186 | addline(convert_kv(key, val, attr_type, attr, cdata)) | ||
| 187 | |||
| 188 | elif hasattr(val, 'isoformat'): # datetime | ||
| 189 | addline(convert_kv(key, val.isoformat(), attr_type, attr, cdata)) | ||
| 190 | |||
| 191 | elif type(val) == bool: | ||
| 192 | addline(convert_bool(key, val, attr_type, attr, cdata)) | ||
| 193 | |||
| 194 | elif isinstance(val, dict): | ||
| 195 | if attr_type: | ||
| 196 | attr['type'] = get_xml_type(val) | ||
| 197 | addline('<%s%s>%s</%s>' % ( | ||
| 198 | key, make_attrstring(attr), | ||
| 199 | convert_dict(val, ids, key, attr_type, item_func, cdata), | ||
| 200 | key | ||
| 201 | ) | ||
| 202 | ) | ||
| 203 | |||
| 204 | elif isinstance(val, collections.Iterable): | ||
| 205 | if attr_type: | ||
| 206 | attr['type'] = get_xml_type(val) | ||
| 207 | # addline('<%s%s>%s</%s>' % ( | ||
| 208 | # key, | ||
| 209 | # make_attrstring(attr), | ||
| 210 | # convert_list(val, ids, key, attr_type, item_func, cdata), | ||
| 211 | # key | ||
| 212 | # ) | ||
| 213 | item_func = lambda x: key | ||
| 214 | addline('%s' % ( | ||
| 215 | convert_list(val, ids, key, attr_type, item_func, cdata), | ||
| 216 | )) | ||
| 217 | |||
| 218 | elif val is None: | ||
| 219 | addline(convert_none(key, val, attr_type, attr, cdata)) | ||
| 220 | |||
| 221 | else: | ||
| 222 | raise TypeError('Unsupported data type: %s (%s)' % ( | ||
| 223 | val, type(val).__name__) | ||
| 224 | ) | ||
| 225 | |||
| 226 | return ''.join(output) | ||
| 227 | |||
| 228 | |||
| 229 | def convert_list(items, ids, parent, attr_type, item_func, cdata): | ||
| 230 | """Converts a list into an XML string.""" | ||
| 231 | output = [] | ||
| 232 | addline = output.append | ||
| 233 | |||
| 234 | item_name = item_func(parent) | ||
| 235 | |||
| 236 | if ids: | ||
| 237 | this_id = get_unique_id(parent) | ||
| 238 | |||
| 239 | for i, item in enumerate(items): | ||
| 240 | attr = {} if not ids else {'id': '%s_%s' % (this_id, i + 1)} | ||
| 241 | if isinstance(item, numbers.Number) or type(item) in (str, unicode): | ||
| 242 | addline(convert_kv(item_name, item, attr_type, attr, cdata)) | ||
| 243 | |||
| 244 | elif hasattr(item, 'isoformat'): # datetime | ||
| 245 | addline(convert_kv(item_name, item.isoformat(), attr_type, attr, cdata)) | ||
| 246 | |||
| 247 | elif type(item) == bool: | ||
| 248 | addline(convert_bool(item_name, item, attr_type, attr, cdata)) | ||
| 249 | |||
| 250 | elif isinstance(item, dict): | ||
| 251 | if not attr_type: | ||
| 252 | addline('<%s>%s</%s>' % ( | ||
| 253 | item_name, | ||
| 254 | convert_dict(item, ids, parent, attr_type, item_func, cdata), | ||
| 255 | item_name, | ||
| 256 | ) | ||
| 257 | ) | ||
| 258 | else: | ||
| 259 | addline('<%s type="dict">%s</%s>' % ( | ||
| 260 | item_name, | ||
| 261 | convert_dict(item, ids, parent, attr_type, item_func, cdata), | ||
| 262 | item_name, | ||
| 263 | ) | ||
| 264 | ) | ||
| 265 | |||
| 266 | elif isinstance(item, collections.Iterable): | ||
| 267 | if not attr_type: | ||
| 268 | addline('<%s %s>%s</%s>' % ( | ||
| 269 | item_name, make_attrstring(attr), | ||
| 270 | convert_list(item, ids, item_name, attr_type, item_func, cdata), | ||
| 271 | item_name, | ||
| 272 | ) | ||
| 273 | ) | ||
| 274 | else: | ||
| 275 | addline('<%s type="list"%s>%s</%s>' % ( | ||
| 276 | item_name, make_attrstring(attr), | ||
| 277 | convert_list(item, ids, item_name, attr_type, item_func, cdata), | ||
| 278 | item_name, | ||
| 279 | ) | ||
| 280 | ) | ||
| 281 | |||
| 282 | elif item is None: | ||
| 283 | addline(convert_none(item_name, None, attr_type, attr, cdata)) | ||
| 284 | |||
| 285 | else: | ||
| 286 | raise TypeError('Unsupported data type: %s (%s)' % ( | ||
| 287 | item, type(item).__name__) | ||
| 288 | ) | ||
| 289 | return ''.join(output) | ||
| 290 | |||
| 291 | |||
| 292 | def convert_kv(key, val, attr_type, attr={}, cdata=False): | ||
| 293 | """Converts a number or string into an XML element""" | ||
| 294 | |||
| 295 | key, attr = make_valid_xml_name(key, attr) | ||
| 296 | |||
| 297 | if attr_type: | ||
| 298 | attr['type'] = get_xml_type(val) | ||
| 299 | attrstring = make_attrstring(attr) | ||
| 300 | return '<%s%s>%s</%s>' % ( | ||
| 301 | key, attrstring, | ||
| 302 | wrap_cdata(val) if cdata == True else escape_xml(val), | ||
| 303 | key | ||
| 304 | ) | ||
| 305 | |||
| 306 | |||
| 307 | def convert_bool(key, val, attr_type, attr={}, cdata=False): | ||
| 308 | """Converts a boolean into an XML element""" | ||
| 309 | |||
| 310 | key, attr = make_valid_xml_name(key, attr) | ||
| 311 | |||
| 312 | if attr_type: | ||
| 313 | attr['type'] = get_xml_type(val) | ||
| 314 | attrstring = make_attrstring(attr) | ||
| 315 | return '<%s%s>%s</%s>' % (key, attrstring, unicode(val).lower(), key) | ||
| 316 | |||
| 317 | |||
| 318 | def convert_none(key, val, attr_type, attr={}, cdata=False): | ||
| 319 | """Converts a null value into an XML element""" | ||
| 320 | |||
| 321 | key, attr = make_valid_xml_name(key, attr) | ||
| 322 | |||
| 323 | if attr_type: | ||
| 324 | attr['type'] = get_xml_type(val) | ||
| 325 | attrstring = make_attrstring(attr) | ||
| 326 | return '<%s%s></%s>' % (key, attrstring, key) | ||
| 327 | |||
| 328 | |||
| 329 | def dicttoxml(obj, root=True, custom_root='root', ids=False, attr_type=True, | ||
| 330 | item_func=default_item_func, cdata=False): | ||
| 331 | """Converts a python object into XML. | ||
| 332 | Arguments: | ||
| 333 | - root specifies whether the output is wrapped in an XML root element | ||
| 334 | Default is True | ||
| 335 | - custom_root allows you to specify a custom root element. | ||
| 336 | Default is 'root' | ||
| 337 | - ids specifies whether elements get unique ids. | ||
| 338 | Default is False | ||
| 339 | - attr_type specifies whether elements get a data type attribute. | ||
| 340 | Default is True | ||
| 341 | - item_func specifies what function should generate the element name for | ||
| 342 | items in a list. | ||
| 343 | Default is 'item' | ||
| 344 | - cdata specifies whether string values should be wrapped in CDATA sections. | ||
| 345 | Default is False | ||
| 346 | """ | ||
| 347 | output = [] | ||
| 348 | addline = output.append | ||
| 349 | if root == True: | ||
| 350 | addline('<?xml version="1.0" encoding="UTF-8" ?>') | ||
| 351 | addline('<%s>%s</%s>' % ( | ||
| 352 | custom_root, | ||
| 353 | convert(obj, ids, attr_type, item_func, cdata, parent=custom_root), | ||
| 354 | custom_root, | ||
| 355 | ) | ||
| 356 | ) | ||
| 357 | else: | ||
| 358 | addline(convert(obj, ids, attr_type, item_func, cdata, parent='')) | ||
| 359 | return ''.join(output) |
-
Please register or sign in to post a comment