Skip to main content

Hi everyone, i have a xml question. In my data (dgn V8) i have an attribute called

igds_linkage{}.xml_data.

It lookes like this:

What i want is to extract the attribute with their value.

For example: attribute = 'Type' Value= 'muur' & attribute= 'IMGEO' Value='bestaand'

I now use an xmlflattener

But my result is an list like this.

You can see that the first item in the list has a different attribute value 'identificatieBAGPND' in stead of Type.

So how can i get the attribute and value from the xml and can i make it dynamic. (extract all list items in to attributes)

If you use the XMLFragmenter with Elements to Match set to "feature" and flattening enabled you will end up with a key-value pair list for each feature

ex.

 

'attribuut{0}' has value `muur'

 

'attribuut{0}.naam' has value `type'

 

'attribuut{1}' has value `bestaad'

 

'attribuut{1}.naam' has value `IMGEO status'

You can then loop through the list and turn each element pair into an attribute.

ex with an attribute creator

@Value(attribuut{0}.naam) ; attribuut{0}

 

If on the other hand you want one feature per attribute you can set the fragmenter to attribuut and you will end up with attribuut = muur, attribuut.naam = type, and you can do the same thing without the list indexes.


I also think @jdh's solution is good enough, but, sorry, I cannot resist to try an XQuery solution...


Assuming the feature has an attribute called "xml_fragment" that stores an XML fragment. e.g.

<SHD>
    <feature datadefinitie="Sleutels" code="SLEUTELS">
        <attribuut naam="gisobjectnummeer">105963</attribuut>
    </feature>
    <feature datadefinitie="IMG" code="SHDV">
        <attribuut naam="type">muur</attribuut>
        <attribuut naam="IMGEO status">bestaand</attribuut>
        <attribuut naam="In onderzoek">Nee</attribuut>
        <attribuut naam="relatieveHoogteligging">0</attribuut>
        <attribuut naam="identificatie">P0027.cdffbb11ae7c4f56a96af8f6c17cefb5</attribuut>
        <attribuut naam="tijadstipRegistratie">20170626172844000</attribuut>
    </feature>
    <feature datadefinitie="GBK_LKI" code="C"></feature>
</SHD>
A JSONTemplater with this expression creates the following JSON object.JSONTemplater | Template Expression (XQuery expression)
let $x := fme:get-xml-attribute("xml_fragment")
let $members := {
    for $a in $x//attribuut
    return '"'||string($a/@naam)||'":"'||$a/text()||'"'
}
return '{'||fn:string-join($members, ',')||'}'
Resulting JSON Object:

 

{
   "gisobjectnummeer" : "105963",
   "type" : "muur",
   "IMGEO status" : "bestaand",
   "In onderzoek" : "Nee",
   "relatieveHoogteligging" : "0",
   "identificatie" : "P0027.cdffbb11ae7c4f56a96af8f6c17cefb5",
   "tijadstipRegistratie" : "20170626172844000"
}
You can then extract and expose individual attributes with a JSONFlattener.

If you use the XMLFragmenter with Elements to Match set to "feature" and flattening enabled you will end up with a key-value pair list for each feature

ex.

 

'attribuut{0}' has value `muur'

 

'attribuut{0}.naam' has value `type'

 

'attribuut{1}' has value `bestaad'

 

'attribuut{1}.naam' has value `IMGEO status'

You can then loop through the list and turn each element pair into an attribute.

ex with an attribute creator

@Value(attribuut{0}.naam) ; attribuut{0}

 

If on the other hand you want one feature per attribute you can set the fragmenter to attribuut and you will end up with attribuut = muur, attribuut.naam = type, and you can do the same thing without the list indexes.

@jdh thank you for your solution. the only problem i have is to make the attribuut{}.naam the attribute name and the attribuut{} value the value of attribuut.naam{}.

 

Every object has its own attributes so i have to split every object and define its attributes.

 


I also think @jdh's solution is good enough, but, sorry, I cannot resist to try an XQuery solution...


Assuming the feature has an attribute called "xml_fragment" that stores an XML fragment. e.g.

<SHD>
    <feature datadefinitie="Sleutels" code="SLEUTELS">
        <attribuut naam="gisobjectnummeer">105963</attribuut>
    </feature>
    <feature datadefinitie="IMG" code="SHDV">
        <attribuut naam="type">muur</attribuut>
        <attribuut naam="IMGEO status">bestaand</attribuut>
        <attribuut naam="In onderzoek">Nee</attribuut>
        <attribuut naam="relatieveHoogteligging">0</attribuut>
        <attribuut naam="identificatie">P0027.cdffbb11ae7c4f56a96af8f6c17cefb5</attribuut>
        <attribuut naam="tijadstipRegistratie">20170626172844000</attribuut>
    </feature>
    <feature datadefinitie="GBK_LKI" code="C"></feature>
</SHD>
A JSONTemplater with this expression creates the following JSON object.JSONTemplater | Template Expression (XQuery expression)
let $x := fme:get-xml-attribute("xml_fragment")
let $members := {
    for $a in $x//attribuut
    return '"'||string($a/@naam)||'":"'||$a/text()||'"'
}
return '{'||fn:string-join($members, ',')||'}'
Resulting JSON Object:

 

{
   "gisobjectnummeer" : "105963",
   "type" : "muur",
   "IMGEO status" : "bestaand",
   "In onderzoek" : "Nee",
   "relatieveHoogteligging" : "0",
   "identificatie" : "P0027.cdffbb11ae7c4f56a96af8f6c17cefb5",
   "tijadstipRegistratie" : "20170626172844000"
}
You can then extract and expose individual attributes with a JSONFlattener.
@takashi Thank you for your solution. the json is new for me and i think i give it a try.

 


@jdh thank you for your solution. the only problem i have is to make the attribuut{}.naam the attribute name and the attribuut{} value the value of attribuut.naam{}.

 

Every object has its own attributes so i have to split every object and define its attributes.

 

And that's where the @Value(attribuut{0}.naam) ; attribuut{0} part comes in - if you put that in an AttributeCreator it will create the attributes you need.

 

 

That technique is what I first thought of too - but perhaps there is a better way. I will look into it.

 


And that's where the @Value(attribuut{0}.naam) ; attribuut{0} part comes in - if you put that in an AttributeCreator it will create the attributes you need.

 

 

That technique is what I first thought of too - but perhaps there is a better way. I will look into it.

 

I actually still use the fme function caller with @SupplyAttributes, but that's a bit esoteric. If I don't need to access the attributes later in the workspace (just write them out dynamically) I would use python.

 


Ah! I see there is already a custom transformer on the FME Hub that will do what you need.

So... do as @jdh suggests and use the XMLFragmenter to create your list of attributes.

Then use a ListKeyValuePairExtractor transformer (you might need FME2017.1) and it will convert your list into true attributes. Simple.


Ah! I see there is already a custom transformer on the FME Hub that will do what you need.

So... do as @jdh suggests and use the XMLFragmenter to create your list of attributes.

Then use a ListKeyValuePairExtractor transformer (you might need FME2017.1) and it will convert your list into true attributes. Simple.

Nice work @sander_s for the hub transformer. Very useful.

 


I also think @jdh's solution is good enough, but, sorry, I cannot resist to try an XQuery solution...


Assuming the feature has an attribute called "xml_fragment" that stores an XML fragment. e.g.

<SHD>
    <feature datadefinitie="Sleutels" code="SLEUTELS">
        <attribuut naam="gisobjectnummeer">105963</attribuut>
    </feature>
    <feature datadefinitie="IMG" code="SHDV">
        <attribuut naam="type">muur</attribuut>
        <attribuut naam="IMGEO status">bestaand</attribuut>
        <attribuut naam="In onderzoek">Nee</attribuut>
        <attribuut naam="relatieveHoogteligging">0</attribuut>
        <attribuut naam="identificatie">P0027.cdffbb11ae7c4f56a96af8f6c17cefb5</attribuut>
        <attribuut naam="tijadstipRegistratie">20170626172844000</attribuut>
    </feature>
    <feature datadefinitie="GBK_LKI" code="C"></feature>
</SHD>
A JSONTemplater with this expression creates the following JSON object.JSONTemplater | Template Expression (XQuery expression)
let $x := fme:get-xml-attribute("xml_fragment")
let $members := {
    for $a in $x//attribuut
    return '"'||string($a/@naam)||'":"'||$a/text()||'"'
}
return '{'||fn:string-join($members, ',')||'}'
Resulting JSON Object:

 

{
   "gisobjectnummeer" : "105963",
   "type" : "muur",
   "IMGEO status" : "bestaand",
   "In onderzoek" : "Nee",
   "relatieveHoogteligging" : "0",
   "identificatie" : "P0027.cdffbb11ae7c4f56a96af8f6c17cefb5",
   "tijadstipRegistratie" : "20170626172844000"
}
You can then extract and expose individual attributes with a JSONFlattener.
wow, I found that the XMLXQueryUpdater can be used to extract individual attributes directly from the XML fragment with this small expression.

 

for $a in //attribuut
return fme:set-attribute($a/@naam, $a/text())

0684Q00000ArMQGQA3.png

Interesting. It would be more useful if the Attributes to Expose parameters would be added to the transformer.

I also think @jdh's solution is good enough, but, sorry, I cannot resist to try an XQuery solution...


Assuming the feature has an attribute called "xml_fragment" that stores an XML fragment. e.g.

<SHD>
    <feature datadefinitie="Sleutels" code="SLEUTELS">
        <attribuut naam="gisobjectnummeer">105963</attribuut>
    </feature>
    <feature datadefinitie="IMG" code="SHDV">
        <attribuut naam="type">muur</attribuut>
        <attribuut naam="IMGEO status">bestaand</attribuut>
        <attribuut naam="In onderzoek">Nee</attribuut>
        <attribuut naam="relatieveHoogteligging">0</attribuut>
        <attribuut naam="identificatie">P0027.cdffbb11ae7c4f56a96af8f6c17cefb5</attribuut>
        <attribuut naam="tijadstipRegistratie">20170626172844000</attribuut>
    </feature>
    <feature datadefinitie="GBK_LKI" code="C"></feature>
</SHD>
A JSONTemplater with this expression creates the following JSON object.JSONTemplater | Template Expression (XQuery expression)
let $x := fme:get-xml-attribute("xml_fragment")
let $members := {
    for $a in $x//attribuut
    return '"'||string($a/@naam)||'":"'||$a/text()||'"'
}
return '{'||fn:string-join($members, ',')||'}'
Resulting JSON Object:

 

{
   "gisobjectnummeer" : "105963",
   "type" : "muur",
   "IMGEO status" : "bestaand",
   "In onderzoek" : "Nee",
   "relatieveHoogteligging" : "0",
   "identificatie" : "P0027.cdffbb11ae7c4f56a96af8f6c17cefb5",
   "tijadstipRegistratie" : "20170626172844000"
}
You can then extract and expose individual attributes with a JSONFlattener.
The XMLXQueryExtractor does the same thing, and also it has the "Attributes to Expose" parameter, so it might be better in this case.

 

0684Q00000ArMTSQA3.png


I also think @jdh's solution is good enough, but, sorry, I cannot resist to try an XQuery solution...


Assuming the feature has an attribute called "xml_fragment" that stores an XML fragment. e.g.

<SHD>
    <feature datadefinitie="Sleutels" code="SLEUTELS">
        <attribuut naam="gisobjectnummeer">105963</attribuut>
    </feature>
    <feature datadefinitie="IMG" code="SHDV">
        <attribuut naam="type">muur</attribuut>
        <attribuut naam="IMGEO status">bestaand</attribuut>
        <attribuut naam="In onderzoek">Nee</attribuut>
        <attribuut naam="relatieveHoogteligging">0</attribuut>
        <attribuut naam="identificatie">P0027.cdffbb11ae7c4f56a96af8f6c17cefb5</attribuut>
        <attribuut naam="tijadstipRegistratie">20170626172844000</attribuut>
    </feature>
    <feature datadefinitie="GBK_LKI" code="C"></feature>
</SHD>
A JSONTemplater with this expression creates the following JSON object.JSONTemplater | Template Expression (XQuery expression)
let $x := fme:get-xml-attribute("xml_fragment")
let $members := {
    for $a in $x//attribuut
    return '"'||string($a/@naam)||'":"'||$a/text()||'"'
}
return '{'||fn:string-join($members, ',')||'}'
Resulting JSON Object:

 

{
   "gisobjectnummeer" : "105963",
   "type" : "muur",
   "IMGEO status" : "bestaand",
   "In onderzoek" : "Nee",
   "relatieveHoogteligging" : "0",
   "identificatie" : "P0027.cdffbb11ae7c4f56a96af8f6c17cefb5",
   "tijadstipRegistratie" : "20170626172844000"
}
You can then extract and expose individual attributes with a JSONFlattener.
The xmlXQueryExtractor does the job. exactly what i was looking for. Thank you @takashi

 


If you use the XMLFragmenter with Elements to Match set to "feature" and flattening enabled you will end up with a key-value pair list for each feature

ex.

 

'attribuut{0}' has value `muur'

 

'attribuut{0}.naam' has value `type'

 

'attribuut{1}' has value `bestaad'

 

'attribuut{1}.naam' has value `IMGEO status'

You can then loop through the list and turn each element pair into an attribute.

ex with an attribute creator

@Value(attribuut{0}.naam) ; attribuut{0}

 

If on the other hand you want one feature per attribute you can set the fragmenter to attribuut and you will end up with attribuut = muur, attribuut.naam = type, and you can do the same thing without the list indexes.

I have exposed 39 attribute pairs along with the default xml attributes using the XML-Fragmenter. They are in the form: Property || Value in the FME Data Inspector. None of the methods above allow me to extract these values.

 

 


Reply