I would like to know since I want to convert these transformers to a custom transformer.
This way didn't work for me:
Thanks,
I would like to know since I want to convert these transformers to a custom transformer.
This way didn't work for me:
Thanks,
I want to rout features with missing values different from normal features. The attributes that needs to be checked for missing values has to be a user parameter.
I already tried some python myself:
The test: if the selected attributes have the value "missing_attribute". Wich was assigned by the NullAttributeMapper.
(I also tried the attributeFilter to filter out the missing values. But the attributefilter also only takes 1 attribute as input and not a attributelist specified by a user.)
1) Probably <IndentationError> will occur when running. Lines of a method definition have to be indented correctly.
2) If a feature had two or more attributes storing "missing_attribute", it will be output repeatedly, because the "self.pyoutput" is called for each "missing_attribute". You should insert "break" (to escape from the loop) after outputting the feature, unless you intend to duplicate a feature which has multiple "missing_attribute".
Now i have to make a duplicate of this pythoncaller and change val == "missing_attribute" in val != "missing_attribute" so i can route the normal features.
The first PythonCaller (val == 'missing_attribute') will output features having an attribute which stores 'missing_attribute'. This probably matches to your requirement.
The second one (val != 'missing_attribute'), however, could also output features having an attribute which stores 'missing_attribute', if one of other selected attributes does not store 'missing_attribute'. Is it your expected behavior?
If your requirement is to classify input features into these two kinds:
(1) features having at least one 'missing' attribute
(2) others (i.e. all the selected attributes store 'non-missing' value),
I would add a flag attribute to the (1) features with a script, expose the flag attribute through the PythonCaller parameter setting (Attributes to Expose), and then test the flag value with the Tester.
-----
# Python Script Example
class FeatureProcessor(object):
def input(self, feature):
attrlist = feature.getAttribute('ATTRLIST')
attrsplit = attrlist.split(' ')
for attribute in attrsplit:
val = feature.getAttribute(attribute)
if val == 'missing_attribute':
feature.setAttribute('_flag', 1) # add the flag attribute
break
self.pyoutput(feature)
-----
In addition, feature.getAttribute returns 'None' if the specified attribute doesn't exist (i.e. missing). If you will leverage it, the NullAttributeMapper may not be essential.
One more.
When an attribute name contains a whitespace within it, splitting ATTRLIST by whitespace will not work as expected. If an attribute name may contain whitespaces, you will have to consider other approach.
FYI.
Takashi
The (val != 'missing_attribute') had indeed unexpected behavior.
Adding a flag attribute in combination with a tester is a smart solution. I used your script example and it works well.
Splitting by whitespace can indeed give trouble. Thanks for bringing that to my attention. Any hints how to solve that with python? Or can I use transformers?
For example, if selected attribute names were A B C and X Y Z, fetched parameter value would be A B C X Y Z. There are no delimiters nor quotations, so it cannot be split into individual names anyhow.
As a workaround, discard the NullAttributeMapper, and you will have to create a published parameter in the Navigator window manually.
Right-click "Published Parameters" > select "Add Parameter" command.
If you create the parameter with Attribute List (comma delimited) type, fetched parameter value will be "A B C","X Y Z". i.e. the attribute names containing whitespaces will be quoted by double quotations.
Then, a PythonCaller with this script adds the flag to the features containing missing attribute, for example.
-----
def processFeature(feature):
attrList = feature.getAttribute('ATTRLIST')
for attr in s.strip('"') for s in attrList.split(',')]:
if feature.getAttribute(attr) == None:
feature.setAttribute('_flag', 1)
break
-----
Note: naturally it doesn't work as expected if an attribute name could contain commas.
Alternatively, you can also use the TclCaller.
If you create the parameter with Attribute List (space delimited) type, fetched parameter value will be "A B C" "X Y Z". It can be used directly as a list structure for a Tcl script.
Then, a TclCaller with this script returns the flag value as the "Destination Attribute", for example.
-----
proc setFlag {} {
foreach attr >FME_GetAttribute "ATTRLIST"] {
if {!eFME_AttributeExists $attr]} {return 1}
}
}
-----
Hope this helps.
I followed your instructions and with help of your examples I wrote this script:
#-----Python script-----
import fme
import fmeobjects
# Template Class Interface:
class FeatureProcessor(object):
def __init__(self):
pass
def input(self,feature):
attrlist = feature.getAttribute('ATTRLIST')
attrsplit = attrlist.split(',')
for attr in attrsplit:
if feature.getAttribute(attr) == None or feature.getAttribute(attr) == '':
feature.setAttribute('_flag', 1)
break
else:
pass
self.pyoutput(feature)
def close(self):
pass
#-----Python script------
Using the script withtin this workbench everything works fine:
Now I finally reached my end-goal wich was to create a custom transformer to check missing attributevalues in user specified attributes.
Thanks for your support!