Hi,
I did that with these string operations.
1) StringReplacer
Remove every namespace prefix ("gml:", "fme:", "xlink:") from the source text.
2) StringConcatenator
Transform the source text into a complete XML document.
e.g. <?xml version="1.0"?><dataset>@Value(source)</dataset>
3) XMLFragmenter
Flatten the XML document with the Flatten option.
Elements to Match: featuremember
4) StringConcatenator
Transform "person.owns.href" (stores "#Building01" etc.) into an XML element.
i.e. <fme:owns xlink:href="@Value(person.owns.href)" />
5) Aggregator
Aggregate the features.
Group By: person.id person.name
List Name: _list
6) ListConcatenator
Concatenate "_list{}.person.owns.href" to create a string consisting of multiple XML elements.
7) StringConcatenator
Construct the required XML element.
i.e. <gml:featuremember> ... </gml:featuremember>
Note that your source text is invalid as XML fragments. You will have to fix it beforehand.
wrong: <fme:person /> --> correct: </fme:person>
There may be more elegant ways.
Takashi
Forgot to comment. Expose these attributes in the XMLFragmenter.
person.id
person.name
person.owns.href
Hello Takashi,
Thank you a lot for your quick answer !!!
The XML fragment is not the 'real' GML, it is only an example written by me.
The real working GML is well formed and has been checked with XMLSpy. But, thanks for pointing up the syntax error.
Parsing XML file is an effective solution, but I agree with you that there may be other ways to solve this problem.
To give more details, I have to transform an ESRI file Geodatabase (or personal Geodatabase), containing a simple m:n RelationShip Class defined in arcCatalog,
into a GML file compliant with an user defined schema. The GML application schema is also validated with XMLSpy.
These are the features defined in the XSD (gml application schema):
I have performed the necessary joins (FeatureMerger, InlineQuerier) and I have assigned roles to xlink_ref attribute based on RelationShip Class.
I tried using 'Group By' attribute in FeatureMerger but doesn't work for me.
I tried using 'Aggregator' transformer (as you can see in the workspace) and also, ListExploder with several transformers but with the same result.
This is my FME workbench:
may be i have to do something more in the join process ???
Thank you very much for your time.
I'm new to FME, so if there were any improvement in my fme workbench no doubt to tell me.
Thanks in advance !
As the first step, to merge feature attributes, two FeatureMergers may be intelligible.
1) FeatureMerger: Merge attributes of "person" feature to "parcel_person" feature.
Send "parcel_person" features to Requestor port, and send "person" features to Supplier port.
- Join On: PERSON_ID
2) FeatureMerger_2: Merge attributes of the Merged feature to "parcel" feature.
Send "parcel" features to Requestor port, and send the Merged features (output of the first FeatureMerger) to Supplier port.
- Join On: PARCEL_ID
- Process Duplicate Suppliers: Yes
- Duplicate Supplier List Name: <specify preferable list name>
The Merged features from the 2nd FeatureMerger will be the source for "Parcel".
On the other hand, apply a ListExploder to the Merged features from the 2nd FeatureMerger, then, aggregate the exploded features with the Aggregator.
- Group By: PERSON_ID
- Mode: Attribute Only
- Keep Input Attribute: Yes
- List Name: <specify preferable list name>
The outputs will be the source for "Person".
If I've understood the Geodatabase schema and your requirement correctly, the sources for "Parcel" and "Person" can be prepared by the procedure above.
After this, you need to transform the structure of attributes into suitable schemas to the destination dataset, but it would be the next step after confirming whether the procedure works fine as expected.
Check if the procedure can fetch required data from the Geodatabase, using inspection tools such as Inspector or Logger.
If you don't need to merge attributes of "parcel" to "person" feature - i.e. if you just need to merge PARCEL_ID to "person", you can aggregate the Merged features from the 1st FeatureMerger to create the source for "Person".
- Group By: PERSON_ID
- Mode: Attribute Only
- Keep Input Attribute: Yes
- List Name: <specify preferable list name>
Ahh... do you perhaps just need to add PERSON_ID(s) to "parcel" features?
If so, a FeatureMerger can be used to do that.
"parcel" --> Requestor
"parcel_person" --> Supplier
- Join On: PARCEL_ID
- Process Duplicate Suppliers: Yes
- Duplicate Supplier List Name: <specify preferable list name>
Hi Takashi,
Many, many thanks for your time !!!
As you say I just need to merge PARCEL_ID to "person" and PERSON_ID to "parcel".
My problem deals with the use of the "list" parameters.
I am able to perform join, and aggregation and so on, but I am not be able to write a list of elements. That's my initial problem.
I have focused the problem only in two features: "person" and "person_parcel" with a 1:m relationship. So, I have created a new workspace with the parameters that you can see in the image but ONLY writes the FIRST xlink element in the list.
The result is coherent with the way I have expressed the parameter value.
The problem is that in "AttributeCopier" is compulsory to indicate ONLY ONE element on the list nor only the list (I have indicated {0}).
So, this is the GML that I get:
<fme:Person gml:id="PERSON.ID002"> <fme:firstname>fisrtname02</fme:firstname> <fme:lastname>lastname02</fme:lastname> <fme:owns xlink:href="17"/> </fme:Person> <fme:Person gml:id="PERSON.ID003"> <fme:firstname>fisrtname03</fme:firstname> <fme:lastname>lastname03</fme:lastname> <fme:owns xlink:href="08"/> </fme:Person> <fme:Person gml:id="PERSON.ID001"> <fme:firstname>fisrtname01</fme:firstname> <fme:lastname>lastname01</fme:lastname> <fme:owns xlink:href="25"/> </fme:Person>
And this GML is what I expect to have with this workspace:
<fme:Person gml:id="PERSON.ID002"> <fme:firstname>fisrtname02</fme:firstname> <fme:lastname>lastname02</fme:lastname> <fme:owns xlink:href="17"/> <fme:owns xlink:href="43"/> </fme:Person> <fme:Person gml:id="PERSON.ID003"> <fme:firstname>fisrtname03</fme:firstname> <fme:lastname>lastname03</fme:lastname> <fme:owns xlink:href="08"/> </fme:Person> <fme:Person gml:id="PERSON.ID001"> <fme:firstname>fisrtname01</fme:firstname> <fme:lastname>lastname01</fme:lastname> <fme:owns xlink:href="25"/> <fme:owns xlink:href="17"/> <fme:owns xlink:href="43"/> </fme:Person>
In fact, the complete GML that i need is like this ( this is written by hand):
<fme:Person gml:id="PERSON.ID002"> <fme:firstname>fisrtname02</fme:firstname> <fme:lastname>lastname02</fme:lastname> <fme:owns xlink:href="#PARCEL.17"/> <fme:owns xlink:href="#PARCEL.43"/> </fme:Person> <fme:Person gml:id="PERSON.ID003"> <fme:firstname>fisrtname03</fme:firstname> <fme:lastname>lastname03</fme:lastname> <fme:owns xlink:href="#PARCEL.08"/> </fme:Person> <fme:Person gml:id="PERSON.ID001"> <fme:firstname>fisrtname01</fme:firstname> <fme:lastname>lastname01</fme:lastname> <fme:owns xlink:href="#PARCEL.25"/> <fme:owns xlink:href="#PARCEL.17"/> <fme:owns xlink:href="#PARCEL.43"/> </fme:Person> <fme:Parcel gml:id="PARCEL.08"> <fme:area>100.0</fme:area> <fme:owner xlink:href="#PERSON.ID003"/> </fme:Parcel> <fme:Parcel gml:id="PARCEL.17"> <fme:area>100.0</fme:area> <fme:owner xlink:href="#PERSON.ID001"/> <fme:owner xlink:href="#PERSON.ID002"/> </fme:Parcel> <fme:Parcel gml:id="PARCEL.25"> <fme:area>100.0</fme:area> <fme:owner xlink:href="#PERSON.ID001"/> </fme:Parcel> <fme:Parcel gml:id="PARCEL.43"> <fme:area>100.0</fme:area> <fme:owner xlink:href="#PERSON.ID001"/> <fme:owner xlink:href="#PERSON.ID002"/> </fme:Parcel>
So, what's wrong in the use of "list" parameter ?
how do I have to use the RelationShipClass where are defined roles 'owns' and 'owner ?
Thanks a lot Takashi and nice weekend !!!
The major issue is how to create all the elements of "owns{}.xlink_href" properly.
This may be a quick way.
1) Rename "PARCEL_ID" of "parcel_person" features to "xlink_href".
2) Aggregate them with the Aggregator.
Group By: PERSON_ID
Mode: Attribute Only
List Name: owns
3) Merge attributes of "person" to the aggregated "parcel_person" features.
Send "parcel_person" features to Requestor port, send "person" features to Supplier port of the FeatureMerger.
Join On: PERSON_ID
Process Duplicate Suppliers: No
4) Rename other attribute names if necessary, then send them to the GML writer feature type.
Have a nice weekend!
Many, many thanks Takashi. It works perfectly !!!!
Best wishes, Ariadna.