PyXB with XML schema containing choice statement - python

i am using pyXB for binding XML.
my schema used at there has choice elements.
so when i convert XML into a python instance
i don't know exactly which element is chosen at choice element.
So in order to distinguish, i have had to use if/else statement considering all cases.
for example, if the choice element has a and b, to distinguish one within a and b
A = binder.CreateFromDocument(xml) #bind into a python instance
#At this point, i don't know which element is included
#So I have to check using if/else
if A.a:
#processing in the case of a
A.a.aa = 'a'
else if A.b:
#processing in the case of b
A.b.bb = 'b'
the example is so simple and if/else looks enough but if the choice element has so many element about more than 100.
that processing(repeated if/else) will be so bad.
is there any other way to know which element is chosen?

Yes; there is a method orderedContent on complex type instances that can be used to determine what elements are present in the instance. This can also be used to recover the document order of elements when order is not enforced by the schema, as described in the user documentation.
Note that the members of the orderedContent list are wrapped in objects that provide information about them, so to get the underlying content binding you have to drill down through the wrapper's value property.

Related

What does isinstance mean combined with ScalarNode, SequenceNode, and MappingNode?

I have googled without success so I would like what does isinstance means combined with yaml ScalarNode, SequenceNode and MappingNode?
(I know already what isinstance is)
For example
if isinstance(v,yaml.ScalarNode):
#do something
elif isinstance(v,yaml.SequenceNode):
#something else
elif isinstance(v, yaml.MappingNode):
#another thing
Node types are a part of YAML's Representation data structure. YAML defines its (de)serialization pipeline as follows:
(source: yaml.org)
The Representation is a, potentially cyclic, graph of nodes. In it, anchors and aliases have been resolved. In PyYAML, you typically use subgraphs of this data structure to implement custom constructors and representers that generate your native objects, as indicated by the arrows in the diagram.
A ScalarNode is a node representing a single scalar in the YAML source or output. A single scalar can be a plain scalar (e.g. foo), a quoted scalar ('foo' or "foo"), or a block scalar (starting with | or >). The scalar content, with escape sequences, newlines, indentation already processed, is available in the field .value as string. This is even true for values that are by default constructed into non-strings. For example, true will by default generate a boolean value, but as ScalarNode, it contains the value "true" as string.
SequenceNode is a node representing a sequence. The value field of a SequenceNode contains a list of nodes that correspond to the items in the sequence.
MappingNode is a node representing a mapping. The value field of a MappingNode contains a list of tuples, where each tuple consists of the key node and the value node.
All nodes have a field tag that contains the resolved tag of the node. i.e. a ScalarNode with value true would typically have the tag yaml.org,2002:bool. The resolved tag depends on the loader you use, for example if you use PyYAML's BaseLoader, true will resolve to a normal string, which is yaml.org,2002:str. In any case, if there was an explicit tag on the node (e.g. !!str, that tag will be in the tag field.
Coming back to the question, this kind of code is typically used in custom constructors. They get a node as input and are to produce a native value and return it. Usually, a custom constructor expects a specific kind of node but if you want to do proper error reporting, you still want to check whether you actually got the kind of node you need. For this, you use the code you posted.

passing fields of an array of collections through functions in python

is there a way of passing a field of an array of collections into a function so that it can still be used to access a element in the collection in python?. i am attempting to search through an array of collections to locate a particular item by comparing it with an identifier. this identifier and field being compared will change as the function is called in different stages of the program. is there a way of passing up the field to the function, to access the required element for comparison?
this is the code that i have tried thus far:
code ...
In your code, M_work is a list. Lists are accessed using an index and this syntax: myList[index]. So that would translate to M_work[place] in your case. Then you say that M_work stores objects which have fields, and you want to access one of these fields by name. To do that, use getattr like this: getattr(M_work[place], field). You can compare the return value to identifier.
Other mistakes in the code you show:
place is misspelled pace at one point.
True is misspelled true at one point.
The body of your loop always returns at the first iteration: there is a return in both the if found == True and else branches. I don't think this is what you want.
You could improve your code by:
noticing that if found == True is equivalent to if found.
finding how you don't actually need the found variable.
looking at Python's for...in loop.

Retrieving a specific set element in Python

Essentially this is what I'm trying to do:
I have a set that I add objects to. These objects have their own equality method, and a set should never have an element equal to another element in the set. However, when attempting to insert an element, if it is equal to another element, I'd like to record a merged version of the two elements. That is, the objects have an "aux" field that is not considered in its equality method. When I'm done adding things, I would like an element's "aux" field to contain a combination of all of the "aux" fields of equal elements I've tried to add.
My thinking was, okay, before adding an element to the set, check to see if it's already in the set. If so, pull it out of the set, combine the two elements, then put it back in. However, the remove method in Python sets doesn't return anything and the pop method returns an arbitrary element.
Can I do what I'm trying to do with sets in Python, or am I barking up the wrong tree (what is the right tree?)
Sounds like you want a defaultdict
from collections import defaultdict
D = defaultdict(list)
D[somekey].append(auxfield)
Edit:
To use your merge function, you can combine the code people have given in the comments
D = {}
for something in yourthings:
if something.key in D:
D[something.key] = something.auxfield
else:
D[something.key] = merge(D[something.key], something.auxfield)

Query PyTables Nested Columns

I have a table with a nested table column, route. Beneath that are two other nested datatypes, master and slave that both have an integer id and string type field.
I would like to run something like table.readWhere('route/master/id==0') but I get "variable route refers to a nested column, not allowed in conditions"
Is there a method to query a nested datatype in pytables?
You have to create variables to be used inside the condition string. One option is to define a variable dictionary:
table.readWhere('rId==0', condvars={'rId': table.cols.route.master.id})
Another option is to define local variables for the columns to be used in the condition.
rId = table.cols.route.master.id
table.readWhere('rId==0')
As this pollutes the namespace, I recommend you to create a function to wrap the code. I tried to reference the column itself, but it seems the interpreter fetches the whole dataset before throwing a NameError.
table.readWhere('table.cols.route.master.id==0') # DOES NOT WORK
More info on the where() method in the library reference.
Building on the answer by streeto, here is a quick way to get access to all the nested columns in a table when constructing a query
condvars = {k.replace('/', '__'): v for k, v in table.colinstances.items()}
result = table.read_where('route__master__id == 0', condvars=condvars)
table.colinstances returns a flat dict whose keys are slash separated paths to all columns (including nested ones) in the table, and whose values are instances of the PyTables Col class located at that path. You can't use the slash separated path in the query, but if you replace with some other separator that is allowed within Python identifiers (in this case I chose double underscores), then everything works fine. You could choose some other separator if you like.

Need to understand function in python

def process_filter_description(filter, images, ial):
'''Return a new list containing only items from list images that pass
the description filter (a str). ial is the related image association list.
Matching is done in a case insensitive manner.
'''
images = []
for items in ial:
Those are the only two lines of code I have so far. What is troubling me is the filter in the function. I really don't know what the filter is supposed to do or how to use it.
In no way am I asking for the full code. I just want help with what the filter is supposed to do and how I can use it.
Like I said in my comment, this is really vague. But I'll try to explain a little about the concept of a filter in python, specifically the filter() function.
The prototype of filter is: iterable <- filter(function, iterable).
iterable is something that can be iterated over. You can look up this term in the docs for a more exact explanation, but for your question, just know that a list is iterable.
function is a function that accepts a single element of the iterable you specify (in this case, an element of the list) and returns a boolean specifying whether the element should exist in the iterable that is returned. If the function returns True, the element will appear in the returned list, if False, it will not.
Here's a short example, showing how you can use the filter() function to filter out all even numbers (which I should point out, is the same as "filtering in" all odd numbers)
def is_odd(i): return i%2
l = [1,2,3,4,5] # This is a list
fl = filter(is_odd, l)
print fl # This will display [1,3,5]
You should convince yourself that is_odd works first. It will return 1 (=True) for odd numbers and 0 (=False) for even numbers.
In practice, you usually use a lambda function instead of defining a single-use top-level function, but you shouldn't worry about that, as this is just fine.
But anyway, you should be able to do something similar to accomplish your goal.
Well it says in the description line:
Return a new list containing only items from list images that pass the description filter (a str)
...
Matching is done in a case insensitive manner
So.. im guessing the filter is just a string, do you have any kind of text associated with the images ? some kind of description or name that could be matched against the filter string ?

Categories

Resources