def __init__(self): self.processor = xml.user_object( "annotation", Annotation, [ xml.user_object("size", Size, [ xml.integer("width"), xml.integer("height"), ]), xml.array( xml.user_object( "object", Object, [ xml.string("name"), xml.user_object( "bndbox", Box, [ xml.floating_point("xmin"), xml.floating_point("ymin"), xml.floating_point("xmax"), xml.floating_point("ymax"), ], alias="box" ) ] ), alias="objects" ), xml.string("filename") ] )
def _plays_to_games(self, data): def after_players_hook(_, status): return status["name"] if "name" in status else "Unknown" plays_processor = xml.dictionary("plays", [ xml.array( xml.dictionary('play', [ xml.integer(".", attribute="id", alias="playid"), xml.dictionary('item', [ xml.string(".", attribute="name", alias="gamename"), xml.integer(".", attribute="objectid", alias="gameid") ], alias='game'), xml.array( xml.dictionary( 'players/player', [ xml.string(".", attribute="name", required=False, default="Unknown") ], required=False, alias='players', hooks=xml.Hooks(after_parse=after_players_hook))) ], required=False, alias="plays")) ]) plays = xml.parse_from_string(plays_processor, data) plays = plays["plays"] return plays
def _collection_to_games(self, data): def after_status_hook(_, status): return [tag for tag, value in status.items() if value == "1"] game_in_collection_processor = xml.dictionary( "items", [ xml.array( xml.dictionary('item', [ xml.integer(".", attribute="objectid", alias="id"), xml.string("name"), xml.string("thumbnail", required=False, alias="image"), xml.string("version/item/thumbnail", required=False, alias="image_version"), xml.dictionary( "status", [ xml.string(".", attribute="fortrade"), xml.string(".", attribute="own"), xml.string(".", attribute="preordered"), xml.string(".", attribute="prevowned"), xml.string(".", attribute="want"), xml.string(".", attribute="wanttobuy"), xml.string(".", attribute="wanttoplay"), xml.string(".", attribute="wishlist"), ], alias='tags', hooks=xml.Hooks(after_parse=after_status_hook)), xml.integer("numplays"), ], required=False, alias="items"), ) ]) collection = xml.parse_from_string(game_in_collection_processor, data) collection = collection["items"] return collection
def get(self): med_processor = xml.dictionary('response', [ xml.dictionary('header', [ xml.string('resultCode'), xml.string('resultMsg') ]), xml.dictionary('body', [ xml.integer('numOfRows'), xml.integer('pageNo'), xml.integer('totalCount'), xml.dictionary('items', [ xml.array(xml.dictionary('item', [ xml.string('INGR_ENG_NAME'), xml.string('INGR_KOR_NAME'), xml.string('ITEM_NAME_ENG'), xml.string('ITEM_NAME_KOR'), xml.string('SELLING_CORP'), xml.string('DOSAGE_FORM'), xml.string('STRENGTH'), xml.string('GROUPING_NO'), xml.string('PMS_EXP_DATE'), xml.string('KOR_SUIT_YN') ])) ]) ]) ]) med_api = requests.get('http://apis.data.go.kr/1470000/' 'MdcinPatentInfoService/' 'getMdcinPatentInfoList?' 'serviceKey=j1p%2FEIuaPbMKsRuWzOMygNZKwyo2LYZzAWWBwZwxFLc%2BTzuRHN8ROyeJYje%2FPEvs7Hsp6OCVK1fQFt5UcaTocA%3D%3D&' 'pageNo=1&startPage=1&numOfRows=100&pageSize=100') med_xml = med_api.text med_dict = xml.parse_from_string(med_processor, med_xml) items = med_dict['body']['items']['item'] return render_template(self.template, items=items)
def test_parse_dictionary_missing(): """Parse a missing dictionary""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> </person> """ demographics = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ]) address = xml.dictionary('address', [ xml.string('street'), xml.integer('zip'), xml.string('state'), ]) person = xml.dictionary('person', [ xml.string('name'), demographics, address, ]) with pytest.raises(xml.MissingValue): xml.parse_from_string(person, xml_string)
class TestSlashDifferentLevels(_ProcessorTestCase): """Process a slash to different levels of the same path""" xml_string = strip_xml(""" <root> <level1> <level2> <valueB>86</valueB> <level3> <valueC>13</valueC> </level3> </level2> <valueA>27</valueA> </level1> </root> """) value = { 'valueB': 86, 'valueA': 27, 'valueC': 13, } processor = xml.dictionary('root', [ xml.integer('level1/level2/valueB', alias='valueB'), xml.integer('level1/valueA', alias='valueA'), xml.integer('level1/level2/level3/valueC', alias='valueC') ])
def _dict_processor(self): hooks = xml.Hooks(after_parse=self._after_parse, before_serialize=self._before_serialize) return xml.dictionary('data', [ xml.integer('a'), xml.integer('b'), xml.integer('c'), ], hooks=hooks)
def insert_xml(): print('Inserting XML data') transaction_processor = xml.dictionary('transaction', [ xml.string('.', attribute='date'), xml.integer('.', attribute='reseller-id'), xml.integer('transactionId'), xml.string('productName'), xml.integer('qty'), xml.floating_point('totalAmount'), xml.string('salesChannel'), xml.dictionary('customer',[xml.string('firstname'), xml.string('lastname'), xml.string('email')]), xml.string('dateCreated'), xml.string('seriesCity') ]) for resellerid in XML_RESELLERS: tran_id = 0 export = generate_xml(resellerid) for day in ALL_DAYS: data = [tran for tran in export if tran['Created Date']== day] for entry in data: entry['transactionId'] = tran_id tran_id += 1 result = [] xml_header = None result.append('<?xml version="1.0" encoding="utf-8"?>') result.append('<transactions>') for tran in data: xml_str = xml.serialize_to_string(transaction_processor, tran, indent=' ') splitted =xml_str.split('\n') result += splitted[1:] result.append('</transactions>') date_nameformat = day.split('-') new_format = date_nameformat[0] + date_nameformat[2] + date_nameformat[1] with open(f"/home/generator/xml/rawDailySales_{new_format}_{resellerid}.xml", 'w') as output_file: output_file.write('\n'.join(result))
def test_parse_dictionary_nested(): """Parse nested dictionaries""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> <address> <street>123 ABC Street</street> <zip>123456</zip> <state>NY</state> </address> </person> """ demographics = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ]) address = xml.dictionary('address', [ xml.string('street'), xml.integer('zip'), xml.string('state'), ]) person = xml.dictionary('person', [ xml.string('name'), demographics, address, ]) expected = { 'name': 'John Doe', 'demographics': { 'age': 25, 'gender': 'male', }, 'address': { 'street': '123 ABC Street', 'zip': 123456, 'state': 'NY', }, } actual = xml.parse_from_string(person, xml_string) assert expected == actual
def json2cdata(input): author_processor = xml.dictionary('rows', [ xml.array(xml.dictionary('row', [ xml.string('qid'), xml.integer('code'), xml.string('answer'), xml.integer('sortorder'), xml.integer('assessment_value'), xml.integer('language'), xml.integer('scale_id'), ]), alias='rows') ]) xmlstr = xml.serialize_to_string(author_processor, input, indent=' ') return xmlstr
def test_user_object_serialize_aliased(): """Serializes an aliased user object""" value = { 'book': 'Harry Potter', 'character': Person().set_values(name='Malfoy', age=17) } processor = xml.dictionary('root', [ xml.string('book'), xml.user_object('person', Person, [xml.string('name'), xml.integer('age')], alias='character') ]) expected = strip_xml(""" <root> <book>Harry Potter</book> <person> <name>Malfoy</name> <age>17</age> </person> </root> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_user_object_parse_aliased(): """Parse an aliased user object""" xml_string = """ <root> <book>Harry Potter</book> <person> <name>Ron</name> <age>18</age> </person> </root> """ processor = xml.dictionary('root', [ xml.string('book'), xml.user_object('person', Person, [xml.string('name'), xml.integer('age')], alias='character') ]) expected = { 'book': 'Harry Potter', 'character': Person().set_values(name='Ron', age=18) } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_parse_array_of_arrays(): """Parse array of arrays""" xml_string = """ <root-array> <values> <value>1</value> <value>17</value> <value>33</value> </values> <values> <value>99</value> </values> </root-array> """ values_array = xml.array(xml.integer('value'), nested='values') root_processor = xml.array(values_array, nested='root-array') expected = [ [1, 17, 33], [99], ] actual = xml.parse_from_string(root_processor, xml_string) assert expected == actual
def test_parse_dictionary_aliased(): """Parses a dictionary value that is aliased""" xml_string = """ <person> <name>John Doe</name> <demographics> <age>25</age> <gender>male</gender> </demographics> </person> """ stats = xml.dictionary('demographics', [ xml.integer('age'), xml.string('gender'), ], alias='stats') person = xml.dictionary('person', [ xml.string('name'), stats, ]) expected = { 'name': 'John Doe', 'stats': { 'age': 25, 'gender': 'male', }, } actual = xml.parse_from_string(person, xml_string) assert expected == actual
def test_parse_array_nested(): """Parse nested array""" xml_string = """ <root> <message>Hello, World!</message> <numbers> <number>1</number> <number>2</number> </numbers> </root> """ numbers_array = xml.array(xml.integer('number'), nested='numbers') processor = xml.dictionary('root', [ xml.string('message'), numbers_array, ]) expected = { 'message': 'Hello, World!', 'numbers': [1, 2], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_processor_locations_parsing(): """Get processor location in hooks callback.""" expected_locations = [ xml.ProcessorLocation(element_path='data', array_index=None), xml.ProcessorLocation(element_path='value', array_index=None) ] def trace(state, _): assert isinstance(state, xml.ProcessorStateView) assert expected_locations == list(state.locations) hooks = xml.Hooks( after_parse=trace, before_serialize=trace, ) processor = xml.dictionary('data', [ xml.integer('value', hooks=hooks), ]) xml_string = strip_xml(""" <data> <value>1</value> </data> """) value = {'value': 1} xml.parse_from_string(processor, xml_string) xml.serialize_to_string(processor, value)
def test_primitive_default_present(): """Parses primitive values with defaults specified""" xml_string = """ <root> <boolean>false</boolean> <float>3.14</float> <int>1</int> <string>Hello, World</string> </root> """ processor = xml.dictionary('root', [ xml.boolean('boolean', required=False, default=True), xml.floating_point('float', required=False, default=0.0), xml.integer('int', required=False, default=0), xml.string('string', required=False, default=''), ]) expected = { 'boolean': False, 'float': 3.14, 'int': 1, 'string': 'Hello, World', } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_parse_primitive_aliased(): """Parses primitive values with aliases""" xml_string = """ <root> <boolean>true</boolean> <float>3.14</float> <int>1</int> <string>Hello, World</string> </root> """ processor = xml.dictionary('root', [ xml.boolean('boolean', alias='b'), xml.floating_point('float', alias='f'), xml.integer('int', alias='i'), xml.string('string', alias='s'), ]) expected = { 'b': True, 'f': 3.14, 'i': 1, 's': 'Hello, World', } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_parse_array_embedded(): """Parse array embedded within its parent element""" xml_string = """ <root> <message>Hello, World!</message> <value>21</value> <value>17</value> <value>90</value> <value>6</value> </root> """ values_array = xml.array(xml.integer('value')) processor = xml.dictionary('root', [ xml.string('message'), values_array, ]) expected = { 'message': 'Hello, World!', 'value': [21, 17, 90, 6], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_parse_array_optional_present(): """Parse optional array that is present""" xml_string = """ <root> <message>Hello, World!</message> <value>45</value> <value>908</value> </root> """ values_array = xml.array(xml.integer('value', required=False), alias='numbers') processor = xml.dictionary('root', [ xml.string('message'), values_array, ]) expected = { 'message': 'Hello, World!', 'numbers': [45, 908], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_user_object_serialize_array(): """Serializes an array of user objects""" value = [ Person().set_values(name='Bob', age=33), Person().set_values(name='Jan', age=24), Person().set_values(name='Tom', age=29) ] processor = xml.array(xml.user_object( 'person', Person, [xml.string('name'), xml.integer('age')]), nested='people') expected = strip_xml(""" <people> <person> <name>Bob</name> <age>33</age> </person> <person> <name>Jan</name> <age>24</age> </person> <person> <name>Tom</name> <age>29</age> </person> </people> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
class TestSlashPrimitiveInNestedRootArray(_ProcessorTestCase): """Process with a slash to a primitive value in an array""" xml_string = strip_xml(""" <people> <person> <demographics> <age>23</age> </demographics> </person> <person> <demographics> <age>27</age> </demographics> </person> <person> <demographics> <age>31</age> </demographics> </person> </people> """) value = [23, 27, 31] processor = xml.array(xml.integer('person/demographics/age', alias='age'), nested='people')
def test_named_tuple_serialize(): """Serialize a namedtuple value""" value = Author(name='Robert A. Heinlein', books=[ Book(title='Starship Troopers', year_published=1959), Book(title='Stranger in a Strange Land', year_published=1961) ]) processor = xml.named_tuple('author', Author, [ xml.string('name'), xml.array(xml.named_tuple('book', Book, [ xml.string('title'), xml.integer('year-published', alias='year_published') ]), alias='books') ]) expected = strip_xml(""" <author> <name>Robert A. Heinlein</name> <book> <title>Starship Troopers</title> <year-published>1959</year-published> </book> <book> <title>Stranger in a Strange Land</title> <year-published>1961</year-published> </book> </author> """) actual = xml.serialize_to_string(processor, value) assert expected == actual
def test_primitive_transform_array_element(): """Transform a primitive value that is an array element""" xml_string = strip_xml(""" <data> <value>3</value> <value>7</value> <value>16</value> </data> """) value = [ 6, 14, 32, ] def _after_parse(_, x): return int(x * 2) def _before_serialize(_, x): return int(x / 2) hooks = xml.Hooks(after_parse=_after_parse, before_serialize=_before_serialize) processor = xml.array(xml.integer('value', hooks=hooks), nested='data') _transform_test_case_run(processor, value, xml_string)
def test_parse_array_nested_empty_optional(): """Parse nested empty array""" xml_string = """ <root> <message>Hello, World!</message> <numbers /> </root> """ numbers_array = xml.array(xml.integer('number', required=False), nested='numbers') processor = xml.dictionary('root', [ xml.string('message'), numbers_array, ]) expected = { 'message': 'Hello, World!', 'numbers': [], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_primitive_transform_attribute(): """Transform a primitive value that is an attribute""" xml_string = strip_xml(""" <data> <element value="3" /> </data> """) value = { 'value': 6, } def _after_parse(_, x): return int(x * 2) def _before_serialize(_, x): return int(x / 2) hooks = xml.Hooks(after_parse=_after_parse, before_serialize=_before_serialize) processor = xml.dictionary( 'data', [xml.integer('element', attribute='value', hooks=hooks)]) _transform_test_case_run(processor, value, xml_string)
def test_user_object_non_root(self): """Custom error message for user object values.""" processor = xml.dictionary('data', [ xml.user_object('user', _UserClass, [ xml.string('name'), xml.integer('age'), ], hooks=self._hooks) ]) xml_string = strip_xml(""" <data> <user> <name>Bob</name> <age>24</age> </user> </data> """) value = {'user': _UserClass(name='Bob', age=24)} location = 'data/user' self._assert_error_message(processor, value, xml_string, location)
def test_parse_array_embedded_aliased(): """Parse array embedded within its parent element""" xml_string = """ <root> <message>Goodbye, World!</message> <value>765</value> <value>3456</value> </root> """ values_array = xml.array(xml.integer('value'), alias='numbers') processor = xml.dictionary('root', [ xml.string('message'), values_array, ]) expected = { 'message': 'Goodbye, World!', 'numbers': [765, 3456], } actual = xml.parse_from_string(processor, xml_string) assert expected == actual
def test_dictionary_non_root(self): """Custom error message for dictionary values.""" processor = xml.dictionary('data', [ xml.dictionary('user', [ xml.string('name'), xml.integer('age'), ], hooks=self._hooks) ]) xml_string = strip_xml(""" <data> <user> <name>Bob</name> <age>24</age> </user> </data> """) value = { 'user': { 'name': 'Bob', 'age': 24, } } location = 'data/user' self._assert_error_message(processor, value, xml_string, location)
def test_named_tuple_transform(): """Transform a named tuple value""" Person = namedtuple('Person', ['name', 'age']) xml_string = strip_xml(""" <person> <name>John</name> <age>24</age> </person> """) value = { 'name': 'John', 'age': 24, } def _after_parse(_, tuple_value): return { 'name': tuple_value.name, 'age': tuple_value.age, } def _before_serialize(_, dict_value): return Person(name=dict_value['name'], age=dict_value['age']) processor = xml.named_tuple('person', Person, [ xml.string('name'), xml.integer('age'), ], hooks=xml.Hooks( after_parse=_after_parse, before_serialize=_before_serialize)) _transform_test_case_run(processor, value, xml_string)